Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add notebook features (Icons, expanding tabs) #340

Open
wants to merge 4 commits into from

1 participant

@sevoku
Collaborator

This one adds two useful features to the Notebook widget:

  • Icons in Tab headers: makes it possible to add an icon in front of a tab label
  • Expandable Tabs: if enabled, expands the tab lables

TODO: MAC backend support (expanding doesn't really fit on MAC)
TODO: WPF expands the tabs only on initialization and resize. fixed: 30c4627

@sevoku
Collaborator

I was able to fix the immediate expansion change on Wpf. So everything works except expanding on Mac, which is ok, since the tabs are very wide on Mac by design and expanding them doesn't really fit.

Thats how it looks like (expanded with icons):
xwt demo application_041
xwp wpf expand notebook tabs
xwp mac notebook tabs icons

@sevoku sevoku modified the milestone: v1.0, v0.3
sevoku added some commits
@sevoku sevoku Add icon support to Notebook tabs (only GTK, WPF)
TODO: MAC
5ff2de6
@sevoku sevoku Add Notebook tab headers expandable (only GTK, WPF)
TODO WPF: First view works. tabs expand only on resize,
          if property is changed after the view has been shown for the first time
TODO: MAC

Conflicts:
	TestApps/Samples/Samples/NotebookSample.cs
d021523
@sevoku sevoku [MAC] Add missing icon support to NotebookBackend 61d2835
@sevoku sevoku [WPF] fix immediate tab label expanding
Invalidate measure of each TabItem, when the ExpandTabLabels
property changes, forcing Wpf to reeavluate the tab sizes.
f79d2e3
@sevoku sevoku changed the title from Add notebook features to Add notebook features (Icons, expanding tabs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 4, 2015
  1. @sevoku
  2. @sevoku

    Add Notebook tab headers expandable (only GTK, WPF)

    sevoku authored
    TODO WPF: First view works. tabs expand only on resize,
              if property is changed after the view has been shown for the first time
    TODO: MAC
    
    Conflicts:
    	TestApps/Samples/Samples/NotebookSample.cs
  3. @sevoku
  4. @sevoku

    [WPF] fix immediate tab label expanding

    sevoku authored
    Invalidate measure of each TabItem, when the ExpandTabLabels
    property changes, forcing Wpf to reeavluate the tab sizes.
This page is out of date. Refresh to see the latest.
View
74 TestApps/Samples/Samples/NotebookSample.cs
@@ -8,12 +8,74 @@ public class NotebookSample: VBox
{
public NotebookSample ()
{
- Notebook nb = new Notebook ();
- nb.Add (new Label ("First tab content"), "First Tab");
- nb.Add (new MyWidget (), "Second Tab");
- nb.Add (new MyTestWidget(), "Third Tab");
- nb.TabOrientation = NotebookTabOrientation.Bottom;
- PackStart (nb, true);
+ Notebook mainNB = new Notebook ();
+ mainNB.TabOrientation = NotebookTabOrientation.Top;
+ mainNB.ExpandTabLabels = true;
+
+ Notebook nb1 = new Notebook ();
+ nb1.Add (new Label ("First tab content"), "First Tab", StockIcons.Information);
+ nb1.Add (new MyWidget (), "Second Tab");
+ nb1.Add (new MyTestWidget(), "Third Tab", StockIcons.Warning);
+ nb1.TabOrientation = NotebookTabOrientation.Left;
+
+
+ Notebook nb2 = new Notebook ();
+ for (int i = 1; i <= 5; i++) {
+ var box = new VBox ();
+ box.PackStart (new Label ("tab " + i + " content"), false);
+ for (int j = 1; j <= i; j++)
+ box.PackStart (new Button ("TEST " + i + " " + j), false, true);
+ box.PackStart (new MyWidget (), true);
+ nb2.Add (box, "Tab " + i);
+ }
+ nb2.TabOrientation = NotebookTabOrientation.Bottom;
+
+ mainNB.Add (nb1, "First Tab", StockIcons.Information);
+ mainNB.Add (nb2, "Second Tab", StockIcons.Warning);
+
+ var box2 = new VBox ();
+ box2.PackStart (new Label ("Third Tab content"), false);
+ box2.PackStart (new Button ("TEST"), false, true);
+ box2.PackStart (new Button ("TEST"), false, true);
+ mainNB.Add (box2, "Third Tab", StockIcons.Information);
+
+
+ var buttons = new HBox ();
+ var btnToggleExpand = new ToggleButton ("Expand Tabs");
+ btnToggleExpand.Toggled += (sender, e) => {
+ if (btnToggleExpand.Active) {
+ mainNB.ExpandTabLabels = true;
+ nb1.ExpandTabLabels = true;
+ nb2.ExpandTabLabels = true;
+ } else {
+ mainNB.ExpandTabLabels = false;
+ nb1.ExpandTabLabels = false;
+ nb2.ExpandTabLabels = false;
+ }
+ };
+
+
+ var btnAddTab = new Button ("Add Tab");
+ btnAddTab.Clicked += (sender, e) => {
+ Notebook nb = new Notebook ();
+ nb.Add (new Label ("Tab " + (mainNB.Tabs.Count + 1) + " content"), "Tab " + (mainNB.Tabs.Count + 1) + " 1", StockIcons.Information);
+ nb.Add (new MyWidget (), "Tab " + (mainNB.Tabs.Count + 1) + " 2");
+ nb.TabOrientation = NotebookTabOrientation.Right;
+ nb.ExpandTabLabels = true;
+ mainNB.Add (nb, "Another Tab " + (mainNB.Tabs.Count + 1));
+ };
+
+ var btnRemoveTab = new Button ("Remove Tab");
+ btnRemoveTab.Clicked += (sender, e) => {
+ if (mainNB.Tabs.IndexOf (mainNB.CurrentTab) > 2)
+ mainNB.Tabs.Remove (mainNB.CurrentTab);
+ };
+ buttons.PackStart (btnToggleExpand);
+ buttons.PackStart (btnAddTab);
+ buttons.PackStart (btnRemoveTab);
+
+ PackStart (mainNB, true);
+ PackEnd (buttons);
}
}
View
37 Xwt.Gtk/Xwt.GtkBackend/NotebookBackend.cs
@@ -73,7 +73,9 @@ void HandleWidgetSwitchPage (object o, Gtk.SwitchPageArgs args)
public void Add (IWidgetBackend widget, NotebookTab tab)
{
- Widget.AppendPage (GetWidgetWithPlacement (widget), CreateLabel (tab));
+ var childW = GetWidgetWithPlacement (widget);
+ Widget.AppendPage (childW, CreateLabel (tab));
+ ((Gtk.Notebook.NotebookChild)(Widget [childW])).TabExpand = ExpandTabLabels;
}
public void Remove (IWidgetBackend widget)
@@ -108,12 +110,41 @@ public void UpdateLabel (NotebookTab tab, string hint)
Widget.TabPos = tabPos;
}
}
+
+ bool expandTabLabels;
+ public bool ExpandTabLabels {
+ get {
+ return expandTabLabels;
+ }
+ set {
+ expandTabLabels = value;
+ foreach (Gtk.Widget child in Widget.AllChildren) {
+ Gtk.Notebook.NotebookChild notebook_child = Widget [child] as Gtk.Notebook.NotebookChild;
+ if (notebook_child != null) {
+ notebook_child.TabExpand = value;
+ notebook_child.TabFill = value;
+ }
+ }
+ }
+ }
Gtk.Widget CreateLabel (NotebookTab tab)
{
Gtk.Label label = new Gtk.Label (tab.Label);
- label.Show ();
- return label;
+ if (tab.Image.IsNull)
+ return label;
+ label.Xalign = 0;
+ label.Yalign = 0.5f;
+ label.Justify = Gtk.Justification.Left;
+ var image = new ImageBox (ApplicationContext, tab.Image.WithDefaultSize (Gtk.IconSize.SmallToolbar));
+ var image_align = new Gtk.Alignment (1, 0.5f, 0, 1);
+ image_align.RightPadding = 6;
+ image_align.Add (image);
+ var box = new Gtk.HBox ();
+ box.Add (image_align);
+ box.Add (label);
+ box.ShowAll ();
+ return box;
}
}
}
View
83 Xwt.WPF/Xwt.WPFBackend/NotebookBackend.cs
@@ -61,12 +61,30 @@ public NotebookBackend ()
}
}
+ public bool ExpandTabLabels {
+ get {
+ return ((WpfNotebook)TabControl).ExpandTabLabels;
+ }
+ set {
+ ((WpfNotebook)TabControl).ExpandTabLabels = value;
+ }
+ }
+
public void Add (IWidgetBackend widget, NotebookTab tab)
{
UIElement element = (UIElement)widget.NativeWidget;
- TabItem ti = new TabItem {
+
+ var header = new SWC.StackPanel { Orientation = SWC.Orientation.Horizontal };
+ var headerImage = new ImageBox (Context);
+ headerImage.ImageSource = tab.Image;
+ if (!tab.Image.IsNull)
+ headerImage.Margin = new Thickness (0, 0, 5, 0);
+ header.Children.Add (headerImage);
+ header.Children.Add (new SWC.TextBlock () { Text = tab.Label, VerticalAlignment = VerticalAlignment.Center });
+
+ WpfTabItem ti = new WpfTabItem {
Content = element,
- Header = tab.Label,
+ Header = header,
Tag = tab
};
@@ -104,8 +122,21 @@ public void Remove (IWidgetBackend widget)
public void UpdateLabel (NotebookTab tab, string hint)
{
TabItem item = TabControl.Items.Cast<TabItem> ().FirstOrDefault (t => t.Tag == tab);
- if (item != null)
- item.Header = tab.Label;
+ if (item != null) {
+ if (hint == "Label") {
+ var headerText = ((SWC.StackPanel)item.Header).Children [1] as SWC.TextBlock;
+ if (headerText != null)
+ headerText.Text = tab.Label;
+ }
+ if (hint == "Image") {
+ var headerImage = ((SWC.StackPanel)item.Header).Children [0] as ImageBox;
+ if (headerImage != null) {
+ headerImage.ImageSource = tab.Image;
+ if (!tab.Image.IsNull)
+ headerImage.Margin = new Thickness (0, 0, 5, 0);
+ }
+ }
+ }
}
public override void EnableEvent (object eventId)
@@ -162,10 +193,54 @@ class WpfNotebook : SWC.TabControl, IWpfWidget
{
public WidgetBackend Backend { get; set; }
+ bool expandTabLabels;
+ public bool ExpandTabLabels {
+ get {
+ return expandTabLabels;
+ }
+ set {
+ expandTabLabels = value;
+ foreach (var tab in Items.Cast<TabItem> ())
+ tab.InvalidateMeasure ();
+ }
+ }
+
protected override System.Windows.Size MeasureOverride (System.Windows.Size constraint)
{
var s = base.MeasureOverride (constraint);
return Backend.MeasureOverride (constraint, s);
}
}
+
+
+ class WpfTabItem: SWC.TabItem
+ {
+ protected override System.Windows.Size MeasureOverride (System.Windows.Size constraint)
+ {
+ var s = base.MeasureOverride (constraint);
+
+ var parentNB = Parent as WpfNotebook;
+
+ if (parentNB != null && parentNB.ExpandTabLabels) {
+ if (parentNB.TabStripPlacement == Dock.Top ||
+ parentNB.TabStripPlacement == Dock.Bottom) {
+ if (double.IsInfinity (constraint.Width))
+ return s;
+ var countBorders = (parentNB.BorderThickness.Left + parentNB.BorderThickness.Right) * (parentNB.Items.Count);
+ var expandedSize = (constraint.Width - countBorders) / parentNB.Items.Count;
+ if (s.Width < expandedSize)
+ s.Width = expandedSize;
+ } else {
+ if (double.IsInfinity (constraint.Height))
+ return s;
+ var countBorders = (parentNB.BorderThickness.Top + parentNB.BorderThickness.Bottom) * (parentNB.Items.Count + 1);
+ var expandedSize = (constraint.Height - countBorders) / parentNB.Items.Count;
+ if (s.Height < expandedSize)
+ s.Height = expandedSize;
+ }
+ }
+ return s;
+ }
+
+ }
}
View
47 Xwt.XamMac/Xwt.Mac/NotebookBackend.cs
@@ -25,12 +25,15 @@
// THE SOFTWARE.
using System;
+using System.Linq;
using Xwt.Backends;
using System.Collections.Generic;
#if MONOMAC
using nint = System.Int32;
using nfloat = System.Single;
+using CGRect = System.Drawing.RectangleF;
+using CGSize = System.Drawing.SizeF;
using MonoMac.Foundation;
using MonoMac.AppKit;
#else
@@ -78,8 +81,10 @@ void HandleWidgetWillSelect (object sender, NSTabViewItemEventArgs e)
#region INotebookBackend implementation
public void Add (IWidgetBackend widget, NotebookTab tab)
{
- NSTabViewItem item = new NSTabViewItem ();
+ TabViewItem item = new TabViewItem ();
item.Label = tab.Label;
+ if (!tab.Image.IsNull)
+ item.Image = tab.Image.ToNSImage ();
item.View = GetWidgetWithPlacement (widget);
Widget.Add (item);
}
@@ -99,8 +104,13 @@ public void UpdateLabel (NotebookTab tab, string hint)
IWidgetBackend widget = (IWidgetBackend) Toolkit.GetBackend (tab.Child);
var v = GetWidget (widget);
var t = FindTab (v);
- if (t != null)
+ if (t != null) {
+ if (!tab.Image.IsNull)
+ t.Image = tab.Image.ToNSImage ();
+ else
+ t.Image = null;
t.Label = tab.Label;
+ }
}
public int CurrentTab {
@@ -144,12 +154,15 @@ public void UpdateLabel (NotebookTab tab, string hint)
Widget.TabViewType = type;
}
}
+
+ public virtual bool ExpandTabLabels { get; set; }
+
#endregion
- NSTabViewItem FindTab (NSView v)
+ TabViewItem FindTab (NSView v)
{
- foreach (var t in Widget.Items) {
- if (t.View == v)
+ foreach (var t in Widget.Items.Cast<TabViewItem>().DefaultIfEmpty()) {
+ if (t != null && t.View == v)
return t;
}
return null;
@@ -163,5 +176,29 @@ class TabView: NSTabView, IViewObject
get { return this; }
}
}
+
+ class TabViewItem : NSTabViewItem
+ {
+ public NSImage Image { get; set; }
+
+ public override void DrawLabel (bool shouldTruncateLabel, CGRect labelRect)
+ {
+ if (Image != null) {
+ Image.Draw (new CGRect (labelRect.X, labelRect.Y, labelRect.Height, labelRect.Height),
+ new CGRect (0, 0, Image.Size.Width, Image.Size.Height), NSCompositingOperation.SourceOver, 1, true, null);
+ labelRect.X += labelRect.Height + 3;
+ labelRect.Width -= labelRect.Height + 3;
+ }
+ base.DrawLabel (shouldTruncateLabel, labelRect);
+ }
+
+ public override CGSize SizeOfLabel (bool computeMin)
+ {
+ var labelSize = base.SizeOfLabel (computeMin);
+ if (Image != null)
+ labelSize.Width += labelSize.Height + 3;
+ return labelSize;
+ }
+ }
}
View
1  Xwt/Xwt.Backends/INotebookBackend.cs
@@ -34,6 +34,7 @@ public interface INotebookBackend: IWidgetBackend, IChildPlacementHandler
void Remove (IWidgetBackend widget);
void UpdateLabel (NotebookTab tab, string hint);
int CurrentTab { get; set; }
+ bool ExpandTabLabels { get; set; }
NotebookTabOrientation TabOrientation { get; set; }
}
View
29 Xwt/Xwt/Notebook.cs
@@ -27,6 +27,7 @@
using System;
using Xwt.Backends;
using System.Windows.Markup;
+using Xwt.Drawing;
namespace Xwt
{
@@ -90,7 +91,15 @@ public void Add (Widget w, string label)
t.Label = label;
tabs.Add (t);
}
-
+
+ public void Add (Widget w, string label, Image image)
+ {
+ NotebookTab t = new NotebookTab ((WidgetBackendHost)BackendHost, w);
+ t.Label = label;
+ t.Image = image != null ? image.GetImageDescription (BackendHost.ToolkitEngine) : ImageDescription.Null;
+ tabs.Add (t);
+ }
+
void OnRemove (Widget child)
{
UnregisterChild (child);
@@ -140,7 +149,12 @@ void OnReplaceChild (NotebookTab tab, Widget oldWidget, Widget newWidget)
get { return Backend.TabOrientation; }
set { Backend.TabOrientation = value; }
}
-
+
+ public bool ExpandTabLabels {
+ get { return Backend.ExpandTabLabels; }
+ set { Backend.ExpandTabLabels = value; }
+ }
+
protected virtual void OnCurrentTabChanged (EventArgs e)
{
if (currentTabChanged != null)
@@ -164,6 +178,7 @@ public class NotebookTab
{
IContainerEventSink<NotebookTab> parent;
string label;
+ ImageDescription image;
Widget child;
internal NotebookTab (IContainerEventSink<NotebookTab> parent, Widget child)
@@ -181,7 +196,15 @@ internal NotebookTab (IContainerEventSink<NotebookTab> parent, Widget child)
parent.ChildChanged (this, "Label");
}
}
-
+
+ public ImageDescription Image {
+ get { return image; }
+ set {
+ image = value;
+ parent.ChildChanged (this, "Image");
+ }
+ }
+
public Widget Child {
get {
return child;
Something went wrong with that request. Please try again.