2 * Copyright(c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.ComponentModel;
19 using System.Collections.Generic;
20 using Tizen.NUI.BaseComponents;
22 namespace Tizen.NUI.Components
25 /// The AppBar class is a class which shows title text and provides navigation
26 /// and action functions on Page.
28 /// <since_tizen> 9 </since_tizen>
29 public partial class AppBar : Control
31 private bool autoNavigationContent = true;
33 private string title = null;
35 private View navigationContent = null;
36 private View titleContent = null;
37 private View actionContent = null;
38 private IEnumerable<View> actionContentViews = null;
40 private View defaultNavigationContent = null;
41 private View defaultTitleContent = null;
42 private View defaultActionContent = null;
44 private Extents navigationPadding;
45 private Extents actionPadding;
46 private ViewStyle actionViewStyle;
47 private ButtonStyle actionButtonStyle;
49 private bool styleApplied = false;
52 /// Creates a new instance of AppBar.
54 /// <since_tizen> 9 </since_tizen>
55 public AppBar() : base()
58 //to use GetNextFocusableView
59 SetKeyboardNavigationSupport(true);
63 /// Creates a new instance of AppBar.
65 /// <param name="style">Creates AppBar by special style defined in UX.</param>
66 /// <since_tizen> 9 </since_tizen>
67 public AppBar(string style) : base(style)
70 //to use GetNextFocusableView
71 SetKeyboardNavigationSupport(true);
75 /// Creates a new instance of AppBar.
77 /// <param name="appBarStyle">Creates AppBar by style customized by user.</param>
78 /// <since_tizen> 9 </since_tizen>
79 public AppBar(AppBarStyle appBarStyle) : base(appBarStyle)
82 //to use GetNextFocusableView
83 SetKeyboardNavigationSupport(true);
87 /// Disposes AppBar and all children on it.
89 /// <param name="type">Dispose type.</param>
90 [EditorBrowsable(EditorBrowsableState.Never)]
91 protected override void Dispose(DisposeTypes type)
98 if (type == DisposeTypes.Explicit)
100 if (navigationContent == defaultNavigationContent)
102 if (navigationContent != null)
104 Utility.Dispose(navigationContent);
109 if (navigationContent != null)
111 Utility.Dispose(navigationContent);
114 if (defaultNavigationContent != null)
116 Utility.Dispose(defaultNavigationContent);
120 if (titleContent == defaultTitleContent)
122 if (titleContent != null)
124 Utility.Dispose(titleContent);
129 if (titleContent != null)
131 Utility.Dispose(titleContent);
134 if (defaultTitleContent != null)
136 Utility.Dispose(defaultTitleContent);
140 if (actionContent == defaultActionContent)
142 if (actionContent != null)
144 Utility.Dispose(actionContent);
149 if (actionContent != null)
151 Utility.Dispose(actionContent);
154 if (defaultActionContent != null)
156 Utility.Dispose(defaultActionContent);
165 /// Navigation content of AppBar.
166 /// NavigationContent is added as a child of AppBar automatically.
167 /// If AutoNavigationContent is set to be true and NavigationContent is not set,
168 /// then default navigation content is automatically displayed.
170 /// <since_tizen> 9 </since_tizen>
171 public View NavigationContent
175 return GetValue(NavigationContentProperty) as View;
179 SetValue(NavigationContentProperty, value);
180 NotifyPropertyChanged();
183 private View InternalNavigationContent
187 return navigationContent;
191 if (navigationContent == value)
196 if (navigationContent != null)
198 Remove(navigationContent);
201 navigationContent = value;
202 if (navigationContent == null)
206 navigationContent.Focusable = true;
212 /// Title text of AppBar.
213 /// Title sets title text to the default title content.
214 /// If TitleContent is not TextLabel, then Title does not set title text of the TitleContent.
216 /// <since_tizen> 9 </since_tizen>
221 return GetValue(TitleProperty) as string;
225 SetValue(TitleProperty, value);
226 NotifyPropertyChanged();
229 private string InternalTitle
244 if (TitleContent is TextLabel textLabel)
246 textLabel.Text = title;
252 /// Title content of AppBar.
253 /// TitleContent is added as a child of AppBar automatically.
254 /// If TitleContent is not TextLabel, then Title does not set title text of the TitleContent.
256 /// <since_tizen> 9 </since_tizen>
257 public View TitleContent
261 return GetValue(TitleContentProperty) as View;
265 SetValue(TitleContentProperty, value);
266 NotifyPropertyChanged();
269 private View InternalTitleContent
277 if (titleContent == value)
282 if (titleContent != null)
284 Remove(titleContent);
287 titleContent = value;
288 if (titleContent == null)
293 if (titleContent is TextLabel textLabel)
295 textLabel.Text = Title;
299 titleContent.Focusable = true;
307 /// Action views of AppBar.
308 /// Action views are added to ActionContent of AppBar.
309 /// If action views and action buttons are set to Actions, then proper style look for action views and action buttons are automatically applied to action views and action buttons.
310 /// e.g. size, button icon color, etc.
311 /// If you do not want to apply framework's style look for action views and action buttons, then please use ActionContent.Add(actionView) instead of setting Actions.
313 /// <since_tizen> 9 </since_tizen>
314 public IEnumerable<View> Actions
318 return actionContentViews;
322 if (ActionContent == null)
324 actionContentViews = value;
328 if (actionContentViews != null)
330 foreach (var oldAction in actionContentViews)
332 if (ActionContent.Children?.Contains(oldAction) == true)
334 ActionContent.Children.Remove(oldAction);
339 actionContentViews = value;
341 if (actionContentViews == null)
346 foreach (var action in actionContentViews)
348 // Apply Action and ActionButton styles.
349 if ((action is Button) && (actionButtonStyle != null))
351 action.ApplyStyle(actionButtonStyle);
353 else if (actionViewStyle != null)
355 action.ApplyStyle(actionViewStyle);
358 ActionContent.Add(action);
364 /// Action content of AppBar.
365 /// ActionContent is added as a child of AppBar automatically.
366 /// Action content contains action views and action buttons by Actions.
367 /// The Action and ActionButton styles of AppBarStyle are applied to actions only by setting Actions.
369 /// <since_tizen> 9 </since_tizen>
370 public View ActionContent
374 return GetValue(ActionContentProperty) as View;
378 SetValue(ActionContentProperty, value);
379 NotifyPropertyChanged();
382 private View InternalActionContent
386 return actionContent;
390 if (actionContent == value)
395 var oldActionContent = actionContent;
396 actionContent = value;
398 // Add views first before remove previous action content
399 // not to cause Garbage Collector collects views.
400 if ((actionContent != null) && (Actions != null))
402 foreach (var action in Actions)
404 // Apply Action and ActionButton styles.
405 if ((action is Button) && (actionButtonStyle != null))
407 action.ApplyStyle(actionButtonStyle);
409 else if (actionViewStyle != null)
411 action.ApplyStyle(actionViewStyle);
414 actionContent.Add(action);
418 if (oldActionContent != null)
420 Remove(oldActionContent);
423 if (actionContent == null)
433 /// Flag to indicate if default navigation content is automatically set or not.
434 /// The default value is true.
435 /// If AutoNavigationContent is set to be true and NavigationContent is not set,
436 /// then default navigation content is automatically displayed.
437 /// If default navigation content is clicked, it calls navigator pop operation.
439 /// <since_tizen> 9 </since_tizen>
440 public bool AutoNavigationContent
444 return (bool)GetValue(AutoNavigationContentProperty);
448 SetValue(AutoNavigationContentProperty, value);
449 NotifyPropertyChanged();
452 private bool InternalAutoNavigationContent
456 return autoNavigationContent;
461 if (autoNavigationContent == value)
466 autoNavigationContent = value;
468 if (autoNavigationContent == true)
470 if (NavigationContent == null)
472 NavigationContent = DefaultNavigationContent;
475 else if (NavigationContent == DefaultNavigationContent)
477 NavigationContent = null;
483 /// Default navigation content of AppBar set automatically by default.
484 /// If AutoNavigationContent is set to be true and NavigationContent is not set,
485 /// then default navigation content is automatically displayed.
486 /// If default navigation content is clicked, it calls navigator pop operation.
488 [EditorBrowsable(EditorBrowsableState.Never)]
489 protected View DefaultNavigationContent
493 // TODO: Do not set default navigation content if there is no previous page.
494 if (defaultNavigationContent == null)
496 defaultNavigationContent = CreateDefaultNavigationContent();
499 return defaultNavigationContent;
504 /// Default title content of AppBar set automatically by default.
505 /// If TitleContent is not set by user, then default title content is
506 /// automatically displayed.
508 [EditorBrowsable(EditorBrowsableState.Never)]
509 protected View DefaultTitleContent
513 if (defaultTitleContent == null)
515 defaultTitleContent = CreateDefaultTitleContent();
518 return defaultTitleContent;
523 /// Default action content of AppBar set automatically by default.
524 /// If ActionContent is not set by user, then default action content is
525 /// automatically displayed.
527 [EditorBrowsable(EditorBrowsableState.Never)]
528 protected View DefaultActionContent
532 if (defaultActionContent == null)
534 defaultActionContent = CreateDefaultActionContent();
537 return defaultActionContent;
542 [EditorBrowsable(EditorBrowsableState.Never)]
543 public override void OnInitialize()
547 SetAccessibilityConstructor(Role.TitleBar);
551 /// Applies style to AppBar.
553 /// <param name="viewStyle">The style to apply.</param>
554 /// <since_tizen> 9 </since_tizen>
555 public override void ApplyStyle(ViewStyle viewStyle)
557 styleApplied = false;
559 base.ApplyStyle(viewStyle);
561 var appBarStyle = viewStyle as AppBarStyle;
563 if (appBarStyle == null)
568 if (appBarStyle.NavigationPadding != null)
570 navigationPadding = new Extents(appBarStyle.NavigationPadding);
573 if (appBarStyle.ActionPadding != null)
575 actionPadding = new Extents(appBarStyle.ActionPadding);
578 // Apply Back Button style.
579 if ((appBarStyle.BackButton != null) && (DefaultNavigationContent is Button button))
581 button.ApplyStyle(appBarStyle.BackButton);
584 // Apply Title style.
585 if ((appBarStyle.TitleTextLabel != null) && (DefaultTitleContent is TextLabel textLabel))
587 textLabel.ApplyStyle(appBarStyle.TitleTextLabel);
590 // Apply ActionCellPadding style.
591 if (DefaultActionContent?.Layout is LinearLayout linearLayout && appBarStyle.ActionCellPadding != null)
593 linearLayout.CellPadding = new Size2D(appBarStyle.ActionCellPadding.Width, appBarStyle.ActionCellPadding.Height);
596 // Apply Action and ActionButton styles.
597 if (DefaultActionContent?.Children != null)
599 foreach (var action in DefaultActionContent?.Children)
601 if ((action is Button) && (appBarStyle.ActionButton != null))
603 action.ApplyStyle(appBarStyle.ActionButton);
605 else if (appBarStyle.ActionView != null)
607 action.ApplyStyle(appBarStyle.ActionView);
612 if (actionButtonStyle == null) actionButtonStyle = (ButtonStyle)appBarStyle.ActionButton?.Clone();
613 else actionButtonStyle.MergeDirectly(appBarStyle.ActionButton);
615 if (actionViewStyle == null) actionViewStyle = (ViewStyle)appBarStyle.ActionView?.Clone();
616 else actionViewStyle.MergeDirectly(appBarStyle.ActionView);
621 // Calculate children's positions based on padding sizes.
626 /// Gets AppBar style.
628 /// <returns>The default AppBar style.</returns>
629 [EditorBrowsable(EditorBrowsableState.Never)]
630 protected override ViewStyle CreateViewStyle()
632 return new AppBarStyle();
635 private void Initialize()
637 // Navigation, Title and Action are located horizontally.
638 Layout = new LinearLayout()
640 LinearOrientation = LinearLayout.Orientation.Horizontal,
641 LinearAlignment = LinearLayout.Alignment.CenterVertical,
644 WidthSpecification = LayoutParamPolicies.MatchParent;
646 if (AutoNavigationContent == true)
648 NavigationContent = DefaultNavigationContent;
651 TitleContent = DefaultTitleContent;
653 ActionContent = DefaultActionContent;
656 private View CreateDefaultNavigationContent()
658 var backButton = new Button();
660 backButton.Clicked += (object sender, ClickedEventArgs args) =>
662 // The page of app bar is popped when default back button is clicked.
663 var page = GetParent() as Page;
666 var navigator = page.GetParent() as Navigator;
667 if (navigator != null)
677 private View CreateDefaultTitleContent()
679 return new TextLabel()
681 HeightSpecification = LayoutParamPolicies.MatchParent,
685 private View CreateDefaultActionContent()
689 Layout = new LinearLayout()
691 LinearOrientation = LinearLayout.Orientation.Horizontal,
692 LinearAlignment = LinearLayout.Alignment.End,
694 WidthSpecification = LayoutParamPolicies.MatchParent,
695 HeightSpecification = LayoutParamPolicies.MatchParent,
699 private void ResetContent()
701 // To keep the order of NavigationContent, TitleContent and ActionContent,
702 // the existing contents are removed and added again.
703 if ((navigationContent != null) && Children.Contains(navigationContent))
705 Remove(navigationContent);
708 if ((titleContent != null) && Children.Contains(titleContent))
710 Remove(titleContent);
713 if ((actionContent != null) && Children.Contains(actionContent))
715 Remove(actionContent);
718 if (navigationContent != null)
720 Add(navigationContent);
723 if (titleContent != null)
728 if (actionContent != null)
733 // Calculate children's positions based on padding sizes.
737 private void CalculatePosition()
739 if (styleApplied == false)
744 // Apply NavigationPadding style.
745 if ((NavigationContent != null) && (navigationPadding != null))
747 if (NavigationContent.Margin.NotEqualTo(navigationPadding))
749 NavigationContent.Margin.CopyFrom(navigationPadding);
753 // Apply ActionPadding style.
754 if ((ActionContent != null) && (actionPadding != null))
756 if (ActionContent.Margin.NotEqualTo(actionPadding))
758 ActionContent.Margin.CopyFrom(actionPadding);
764 /// ToDo : only key navigation is enabled, but value editing is not yet added. for example, after enter key and up/down key the value need be changed.
766 /// <param name="currentFocusedView"></param>
767 /// <param name="direction"></param>
768 /// <param name="loopEnabled"></param>
769 /// <returns></returns>
770 [EditorBrowsable(EditorBrowsableState.Never)]
771 public override View GetNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
773 if (currentFocusedView == null)
775 if (navigationContent != null && navigationContent.Focusable)
777 return navigationContent;
779 else if (titleContent != null && titleContent.Focusable)
788 else if (currentFocusedView == this)
792 else if (currentFocusedView == navigationContent)
794 if (direction == View.FocusDirection.Up)
798 else if (direction == View.FocusDirection.Right)
800 if (titleContent != null && titleContent.Focusable)
809 else if (direction == View.FocusDirection.Down)
813 else if (direction == View.FocusDirection.Left)
818 else if (currentFocusedView == titleContent)
820 if (direction == View.FocusDirection.Up)
824 else if (direction == View.FocusDirection.Right)
828 else if (direction == View.FocusDirection.Down)
832 else if (direction == View.FocusDirection.Left)
834 if (navigationContent != null && navigationContent.Focusable)
836 return navigationContent;
848 [EditorBrowsable(EditorBrowsableState.Never)]
849 protected internal override View PassFocusableViewInsideIfNeeded()
851 if (navigationContent != null && navigationContent.Focusable)
853 return navigationContent;
855 else if (titleContent != null && titleContent.Focusable)