From ab3c759c7b951c45ac5090014b112a76d7bfb477 Mon Sep 17 00:00:00 2001 From: Lluis Sanchez Gual Date: Wed, 14 Dec 2011 13:11:34 +0100 Subject: [PATCH] Implemented table layout --- Samples/MainWindow.cs | 1 + Samples/Samples.csproj | 1 + Samples/Samples/Boxes.cs | 13 +- Samples/Samples/Tables.cs | 70 +++ Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs | 1 + Xwt.Mac/Xwt.Mac/MacEngine.cs | 1 + Xwt/Xwt/Canvas.cs | 4 +- Xwt/Xwt/Table.cs | 659 ++++++++++++++++++++++++---- 8 files changed, 661 insertions(+), 89 deletions(-) create mode 100644 Samples/Samples/Tables.cs diff --git a/Samples/MainWindow.cs b/Samples/MainWindow.cs index b5a1f49a..21879077 100644 --- a/Samples/MainWindow.cs +++ b/Samples/MainWindow.cs @@ -59,6 +59,7 @@ namespace Samples AddSample (null, "List View", typeof(ListView1)); AddSample (null, "Notebook", typeof(NotebookSample)); // AddSample (null, "Scroll View", typeof(ScrollWindowSample)); + AddSample (null, "Tables", typeof(Tables)); AddSample (null, "Text Entry", typeof(TextEntries)); AddSample (null, "Windows", typeof(Windows)); diff --git a/Samples/Samples.csproj b/Samples/Samples.csproj index 287c059c..f705db24 100644 --- a/Samples/Samples.csproj +++ b/Samples/Samples.csproj @@ -61,6 +61,7 @@ + diff --git a/Samples/Samples/Boxes.cs b/Samples/Samples/Boxes.cs index 77b89313..4c0e043e 100644 --- a/Samples/Samples/Boxes.cs +++ b/Samples/Samples/Boxes.cs @@ -55,7 +55,7 @@ namespace Samples class SimpleBox: Canvas { - double coreSize; + Size coreSize; double margin = 1; public Color Color { get; set; } @@ -63,10 +63,17 @@ namespace Samples public SimpleBox (double coreSize) { Color = new Color (0.5, 0.5, 1); - this.coreSize = coreSize; + this.coreSize = new Size (coreSize, coreSize); MinSize = new Size (coreSize + margin * 2, coreSize + margin * 2); } + public SimpleBox (double coreWidth, double coreHeight) + { + Color = new Color (0.5, 0.5, 1); + this.coreSize = new Size (coreWidth, coreHeight); + MinSize = new Size (coreSize.Width + margin * 2, coreSize.Height + margin * 2); + } + protected override void OnDraw (Context ctx) { ctx.SetColor (new Color (0.5, 0.5, 0.5)); @@ -76,7 +83,7 @@ namespace Samples ctx.Rectangle (Bounds.Inflate (-margin, -margin)); ctx.Fill (); ctx.SetColor (Color); - ctx.Rectangle (Bounds.Width / 2 - coreSize / 2, Bounds.Height / 2 - coreSize / 2, coreSize, coreSize); + ctx.Rectangle (Bounds.Width / 2 - coreSize.Width / 2, Bounds.Height / 2 - coreSize.Height / 2, coreSize.Width, coreSize.Height); ctx.Fill (); } } diff --git a/Samples/Samples/Tables.cs b/Samples/Samples/Tables.cs new file mode 100644 index 00000000..de45ab6f --- /dev/null +++ b/Samples/Samples/Tables.cs @@ -0,0 +1,70 @@ +// +// Tables.cs +// +// Author: +// Lluis Sanchez Gual +// +// Copyright (c) 2011 Xamarin Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Xwt; + +namespace Samples +{ + public class Tables: VBox + { + public Tables () + { + Table t = new Table (); + + SimpleBox b = new SimpleBox (200, 20); + t.Attach (b, 0, 1, 0, 1); + + b = new SimpleBox (10, 20); + t.Attach (b, 1, 2, 0, 1); + + b = new SimpleBox (500, 20); + t.Attach (b, 0, 2, 1, 2, AttachOptions.Expand, AttachOptions.Expand); + + b = new SimpleBox (600, 20); + t.Attach (b, 1, 3, 2, 3); + + b = new SimpleBox (200, 20); + t.Attach (b, 2, 3, 3, 4); + + b = new SimpleBox (900, 20); + t.Attach (b, 0, 3, 4, 5); + + PackStart (t); + + HBox box = new HBox (); + PackStart (box); + t = new Table (); + t.Attach (new Label ("One:"), 0, 1, 0, 1); + t.Attach (new TextEntry (), 1, 2, 0, 1); + t.Attach (new Label ("Two:"), 0, 1, 1, 2); + t.Attach (new TextEntry (), 1, 2, 1, 2); + t.Attach (new Label ("Three:"), 0, 1, 2, 3); + t.Attach (new TextEntry (), 1, 2, 2, 3); + box.PackStart (t); + } + } +} + diff --git a/Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs b/Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs index c0e40b9e..0871d97f 100755 --- a/Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs +++ b/Xwt.Gtk/Xwt.GtkBackend/GtkEngine.cs @@ -62,6 +62,7 @@ namespace Xwt.GtkBackend WidgetRegistry.RegisterBackend (typeof(Xwt.ToggleButton), typeof(ToggleButtonBackend)); WidgetRegistry.RegisterBackend (typeof(Xwt.ImageView), typeof(ImageViewBackend)); WidgetRegistry.RegisterBackend (typeof(Xwt.Backends.IAlertDialogBackend), typeof(AlertDialogBackend)); + WidgetRegistry.RegisterBackend (typeof(Xwt.Table), typeof(BoxBackend)); } public override void RunApplication () diff --git a/Xwt.Mac/Xwt.Mac/MacEngine.cs b/Xwt.Mac/Xwt.Mac/MacEngine.cs index ffb32f79..615ed3ea 100644 --- a/Xwt.Mac/Xwt.Mac/MacEngine.cs +++ b/Xwt.Mac/Xwt.Mac/MacEngine.cs @@ -69,6 +69,7 @@ namespace Xwt.Mac WidgetRegistry.RegisterBackend (typeof(Xwt.ComboBox), typeof(ComboBoxBackend)); WidgetRegistry.RegisterBackend (typeof(Xwt.TextEntry), typeof(TextEntryBackend)); WidgetRegistry.RegisterBackend (typeof(Xwt.ImageView), typeof(ImageViewBackend)); + WidgetRegistry.RegisterBackend (typeof(Xwt.Table), typeof(BoxBackend)); } public override void RunApplication () diff --git a/Xwt/Xwt/Canvas.cs b/Xwt/Xwt/Canvas.cs index 5867687c..3e27e5b2 100644 --- a/Xwt/Xwt/Canvas.cs +++ b/Xwt/Xwt/Canvas.cs @@ -234,12 +234,12 @@ namespace Xwt protected override WidgetSize OnGetPreferredWidth () { - return new WidgetSize (minSize.Width, naturalSize.Width); + return new WidgetSize (minSize.Width); } protected override WidgetSize OnGetPreferredHeight () { - return new WidgetSize (minSize.Height, naturalSize.Width); + return new WidgetSize (minSize.Height); } protected override WidgetSize OnGetPreferredHeightForWidth (double width) diff --git a/Xwt/Xwt/Table.cs b/Xwt/Xwt/Table.cs index 021fedcb..7ed8ba97 100755 --- a/Xwt/Xwt/Table.cs +++ b/Xwt/Xwt/Table.cs @@ -25,146 +25,637 @@ // THE SOFTWARE. using System; +using System.Linq; +using System.Collections.Generic; +using System.ComponentModel; + using Xwt.Backends; +using System.Windows.Markup; namespace Xwt { - public class Table + public class Table: Widget { -/* new ITableBackend Backend { - get { return (ITableBackend) base.Backend; } + ChildrenCollection children; + double defaultRowSpacing = 6; + double defaultColSpacing = 6; + Dictionary rowSpacing; + Dictionary colSpacing; + + protected new class EventSink: Widget.EventSink, ICollectionEventSink, IContainerEventSink + { + public void AddedItem (TablePlacement item, int index) + { + ((Table)Parent).OnAdd (item.Child, item); + } + + public void RemovedItem (TablePlacement item, int index) + { + ((Table)Parent).OnRemove (item.Child); + } + + public void ChildChanged (TablePlacement child, string hint) + { + ((Table)Parent).OnChildChanged (child, hint); + } + + public void ChildReplaced (TablePlacement child, Widget oldWidget, Widget newWidget) + { + ((Table)Parent).OnReplaceChild (child, oldWidget, newWidget); + } + } + + protected override Widget.EventSink CreateEventSink () + { + return new EventSink (); + } + + new IBoxBackend Backend { + get { return (IBoxBackend) base.Backend; } } public Table () { + children = new ChildrenCollection ((EventSink)WidgetEventSink); } - public void Attach (Widget w, int left, int right, int top, int bottom) - { - TablePlacement p = new TablePlacement (w); - p.LeftAttach = left; - p.RightAttach = right; - p.TopAttach = top; - p.BottomAttach = bottom; - OnAdd (w, p); + [DefaultValue(6)] + public double DefaultRowSpacing { + get { return defaultRowSpacing; } + set { defaultRowSpacing = value; OnPreferredSizeChanged (); } } - protected override void OnAdd (Widget child, ChildPlacement placement) + [DefaultValue(6)] + public double DefaultColumnSpacing { + get { return defaultColSpacing; } + set { defaultColSpacing = value; OnPreferredSizeChanged (); } + } + + public void SetRowSpacing (int row, double spacing) { - if (placement == null) - placement = new TablePlacement (child); + if (rowSpacing == null) + rowSpacing = new Dictionary (); + rowSpacing [row] = spacing; + OnPreferredSizeChanged (); + } + + public void SetColumnSpacing (int col, double spacing) + { + if (colSpacing == null) + colSpacing = new Dictionary (); + colSpacing [col] = spacing; + OnPreferredSizeChanged (); + } + + public ChildrenCollection Placements { + get { return children; } + } + + public IEnumerable Children { + get { return children.Select (c => c.Child); } + } + + public void Attach (Widget widget, int left, int right, int top, int bottom) + { + Attach (widget, left, right, top, bottom, AttachOptions.Fill | AttachOptions.Expand, AttachOptions.Fill | AttachOptions.Expand); + } + + public void Attach (Widget widget, int left, int right, int top, int bottom, AttachOptions xOptions, AttachOptions yOptions) + { + var p = new TablePlacement ((EventSink)WidgetEventSink, widget) { + Left = left, + Right = right, + Top = top, + Bottom = bottom, + XOptions = xOptions, + YOptions = yOptions + }; + children.Add (p); + } + + public bool Remove (Widget widget) + { + for (int n=0; n + /// Removes all children + /// + public void Clear () + { + children.Clear (); + } + + void OnAdd (Widget child, TablePlacement placement) + { + RegisterChild (child); + Backend.Add ((IWidgetBackend)GetBackend (child)); + OnPreferredSizeChanged (); + } + + void OnRemove (Widget child) + { + UnregisterChild (child); + Backend.Remove ((IWidgetBackend)GetBackend (child)); + OnPreferredSizeChanged (); + } + + void OnChildChanged (TablePlacement placement, object hint) + { + OnPreferredSizeChanged (); + } + + internal protected virtual void OnReplaceChild (TablePlacement placement, Widget oldWidget, Widget newWidget) + { + if (oldWidget != null) + OnRemove (oldWidget); + OnAdd (newWidget, placement); + } + + protected override void OnReallocate () + { + var size = Backend.Size; + var mode = ((IWidgetSurface)this).SizeRequestMode; + if (mode == SizeRequestMode.HeightForWidth) { + CalcDefaultSizes (mode, size.Width, false, true); + CalcDefaultSizes (mode, size.Height, true, true); + } else { + CalcDefaultSizes (mode, size.Height, true, true); + CalcDefaultSizes (mode, size.Width, false, true); + } + + foreach (var bp in children) { + if (!bp.Child.Visible) + continue; + Backend.SetAllocation ((IWidgetBackend)GetBackend (bp.Child), new Rectangle (bp.NextX, bp.NextY, bp.NextWidth, bp.NextHeight)); + ((IWidgetSurface)bp.Child).Reallocate (); + } + } + + double GetSpacing (int cell, bool isRow) + { + double sp; + if (isRow) { + if (rowSpacing != null && rowSpacing.TryGetValue (cell, out sp)) + return sp; + else + return defaultRowSpacing; + } else { + if (colSpacing != null && colSpacing.TryGetValue (cell, out sp)) + return sp; + else + return defaultColSpacing; + } + } + + void CalcDefaultSizes (SizeRequestMode mode, bool calcHeights, out TablePlacement[] visibleChildren, out Dictionary fixedSizesByCell, out HashSet cellsWithExpand, out WidgetSize[] sizes, out double spacing) + { + bool useLengthConstraint = mode == SizeRequestMode.HeightForWidth && calcHeights || mode == SizeRequestMode.WidthForHeight && !calcHeights; + visibleChildren = children.Where (b => b.Child.Visible).ToArray (); + int lastCell = 0; - base.OnAdd (child, placement); - Backend.Attach ((IWidgetBackend)GetBackend (child), (TablePlacement) placement); + fixedSizesByCell = new Dictionary (); + cellsWithExpand = new HashSet (); + HashSet cellsWithWidget = new HashSet (); + sizes = new WidgetSize [visibleChildren.Length]; + + // Get the size of each widget and store the fixed sizes for widget which don't span more than one cell + + for (int n=0; n lastCell) + lastCell = end; + + // Check if the cell is expandable and store the value + AttachOptions ops = calcHeights ? bp.YOptions : bp.XOptions; + for (int i=start; i < end; i++) { + cellsWithWidget.Add (i); + if ((ops & AttachOptions.Expand) != 0) + cellsWithExpand.Add (i); + } + + WidgetSize s; + if (useLengthConstraint) + s = GetPreferredLengthForSize (mode, bp.Child, calcHeights ? bp.NextWidth : bp.NextHeight); + else + s = GetPreferredSize (calcHeights, bp.Child); + sizes [n] = s; + if (end == start + 1) { + bool changed = false; + WidgetSize fs; + fixedSizesByCell.TryGetValue (start, out fs); + if (s.MinSize > fs.MinSize) { + fs.MinSize = s.MinSize; + changed = true; + } + if (s.NaturalSize > fs.NaturalSize) { + fs.NaturalSize = s.NaturalSize; + changed = true; + } + if (changed) + fixedSizesByCell [start] = fs; + } + } + + // For widgets that span more than one cell, calculate the floating size, that is, the size + // which is not taken by other fixed size widgets + + List widgetsToAdjust = new List (); + Dictionary growSizes = new Dictionary (); + + for (int n=0; n GetStartAttach (bp, calcHeights) <= n && GetEndAttach (bp, calcHeights) > n).ToArray (); + WidgetSize maxv = new WidgetSize (0); + TablePlacement maxtMin = null; + TablePlacement maxtNatural = null; + + foreach (var bp in colCells) { + WidgetSize cv = growSizes[bp][n - GetStartAttach (bp, calcHeights)]; + if (cv.MinSize > maxv.MinSize) { + maxv.MinSize = cv.MinSize; + maxtMin = bp; + } + if (cv.NaturalSize > maxv.NaturalSize) { + maxv.NaturalSize = cv.NaturalSize; + maxtNatural = bp; + } + } + foreach (var bp in colCells) { + WidgetSize[] widgetGrows = growSizes[bp]; + int cellIndex = n - GetStartAttach (bp, calcHeights); + if (bp != maxtMin) { + double cv = widgetGrows[cellIndex].MinSize; + double splitExtraSpace = (maxv.MinSize - cv) / (widgetGrows.Length - 1); + for (int i=0; i finalGrowTable = new Dictionary (); + + foreach (var bp in widgetsToAdjust) { + int start = GetStartAttach (bp, calcHeights); + int end = GetEndAttach (bp, calcHeights); + WidgetSize[] widgetGrows = growSizes[bp]; + for (int n=start; n curGrow.MinSize) + curGrow.MinSize = val.MinSize; + if (val.NaturalSize > curGrow.NaturalSize) + curGrow.NaturalSize = val.NaturalSize; + finalGrowTable [n] = curGrow; + } + } + + foreach (var it in finalGrowTable) { + WidgetSize ws; + fixedSizesByCell.TryGetValue (it.Key, out ws); + fixedSizesByCell [it.Key] = it.Value + ws; + } + + spacing = 0; + for (int n=1; n fixedSizesByCell; + HashSet cellsWithExpand; + WidgetSize[] sizes; + double spacing; + + CalcDefaultSizes (mode, calcHeights, out visibleChildren, out fixedSizesByCell, out cellsWithExpand, out sizes, out spacing); + + double naturalSize = 0; + + // Get the total natural size + foreach (var ws in fixedSizesByCell.Values) + naturalSize += ws.NaturalSize; + + double remaining = totalSize - naturalSize - spacing; + + if (remaining < 0) { + // The box is not big enough to fit the widgets using its natural size. + // We have to shrink the cells + + // List of cell indexes that we have to shrink + var toShrink = new List (fixedSizesByCell.Keys); + + // The total amount we have to shrink + double shrinkSize = -remaining; + + while (toShrink.Count > 0 && shrinkSize > 0) { + SizeSplitter sizePart = new SizeSplitter (shrinkSize, toShrink.Count); + shrinkSize = 0; + for (int i=0; i < toShrink.Count; i++) { + int n = toShrink[i]; + double reduction = sizePart.NextSizePart (); + WidgetSize size; + fixedSizesByCell.TryGetValue (n, out size); + size.NaturalSize -= reduction; + + if (size.NaturalSize < size.MinSize) { + // If the widget can't be shrinked anymore, we remove it from the shrink list + // and increment the remaining shrink size. We'll loop again and this size will be + // substracted from the cells which can still be reduced + shrinkSize += (size.MinSize - size.NaturalSize); + size.NaturalSize = size.MinSize; + toShrink.RemoveAt (i); + i--; + } + fixedSizesByCell [n] = size; + } + } + } + else { + int nexpands = cellsWithExpand.Count; + var expandRemaining = new SizeSplitter (remaining, nexpands); + foreach (var c in cellsWithExpand) { + WidgetSize ws; + fixedSizesByCell.TryGetValue (c, out ws); + ws.NaturalSize += expandRemaining.NextSizePart (); + fixedSizesByCell [c] = ws; + } + } + + for (int n=0; n GetStartAttach (c, calcHeights)).ToArray(); + var cells = fixedSizesByCell.OrderBy (c => c.Key); + double offset = 0; + int n = 0; + foreach (var c in cells) { + if (c.Key > 0) + offset += GetSpacing (c.Key, calcHeights); + while (n < sortedChildren.Length && GetStartAttach (sortedChildren[n], calcHeights) == c.Key) { + // In the loop above we store the offset of the widget inside the cell in the NextX/Y field + // so now we have to add (not just assign) the offset of the cell to NextX/Y + if (calcHeights) + sortedChildren[n].NextY += offset; + else + sortedChildren[n].NextX += offset; + n++; + } + offset += c.Value.NaturalSize; + } + } + } + + WidgetSize CalcSize (bool calcHeights) + { + TablePlacement[] visibleChildren; + Dictionary fixedSizesByCell; + HashSet cellsWithExpand; + WidgetSize[] sizes; + double spacing; + SizeRequestMode mode = calcHeights ? SizeRequestMode.WidthForHeight : SizeRequestMode.HeightForWidth; + + CalcDefaultSizes (mode, calcHeights, out visibleChildren, out fixedSizesByCell, out cellsWithExpand, out sizes, out spacing); + + WidgetSize size = new WidgetSize (spacing); + foreach (var s in fixedSizesByCell.Values) + size += s; + return size; + } + + protected override WidgetSize OnGetPreferredWidth () + { + return CalcSize (false); + } + + protected override WidgetSize OnGetPreferredHeight () + { + return CalcSize (true); + } + + protected override WidgetSize OnGetPreferredHeightForWidth (double width) + { + CalcDefaultSizes (SizeRequestMode.HeightForWidth, width, false, false); + return CalcSize (true); + } + + protected override WidgetSize OnGetPreferredWidthForHeight (double height) + { + CalcDefaultSizes (SizeRequestMode.WidthForHeight, height, true, false); + return CalcSize (false); + } + + int GetStartAttach (TablePlacement tp, bool calcHeight) + { + if (calcHeight) + return tp.Top; + else + return tp.Left; + } + + int GetEndAttach (TablePlacement tp, bool calcHeight) + { + if (calcHeight) + return tp.Bottom; + else + return tp.Right; + } + + WidgetSize GetPreferredSize (bool calcHeight, Widget w) + { + if (calcHeight) + return ((IWidgetSurface)w).GetPreferredHeight (); + else + return ((IWidgetSurface)w).GetPreferredWidth (); + } + + WidgetSize GetPreferredLengthForSize (SizeRequestMode mode, Widget w, double width) + { + IWidgetSurface surface = w; + if (mode == SizeRequestMode.WidthForHeight) + return surface.GetPreferredWidthForHeight (width); + else + return surface.GetPreferredHeightForWidth (width); + } } -/* public class TablePlacement: ChildPlacement + [ContentProperty("Child")] + public class TablePlacement { - int leftAttach; - int rightAttach; - int topAttach; - int bottomAttach; - AttachOptions xOptions = AttachOptions.Fill; - AttachOptions yOptions = AttachOptions.Fill; - int xPadding; - int yPadding; + IContainerEventSink parent; + int left, right, top, bottom; + AttachOptions xOptions, yOptions; + Widget child; - internal TablePlacement (Widget child): base (child) + internal TablePlacement (IContainerEventSink parent, Widget child) { + this.parent = parent; + this.child = child; } - public int LeftAttach { + internal double NextWidth; + internal double NextHeight; + internal double NextX; + internal double NextY; + + public int Left { get { - return this.leftAttach; + return left; } set { - leftAttach = value; - NotifyChanged (TablePlacementChange.LeftAttach); + left = value; + parent.ChildChanged (this, "Left"); } } - - public int RightAttach { + + public int Right { get { - return this.rightAttach; + return right; } set { - rightAttach = value; - NotifyChanged (TablePlacementChange.RightAttach); + right = value; + parent.ChildChanged (this, "Right"); } } - - public int TopAttach { + + public int Top { get { - return this.topAttach; + return top; } set { - topAttach = value; - NotifyChanged (TablePlacementChange.TopAttach); + top = value; + parent.ChildChanged (this, "Top"); } } - - public int BottomAttach { + + public int Bottom { get { - return this.bottomAttach; + return bottom; } set { - bottomAttach = value; - NotifyChanged (TablePlacementChange.BottomAttach); + bottom = value; + parent.ChildChanged (this, "Bottom"); } } - + + public Widget Child { + get { return child; } + set { + var old = child; + child = value; + parent.ChildReplaced (this, old, value); + } + } + public AttachOptions XOptions { - get { - return this.xOptions; - } + get { return xOptions; } set { - xOptions = value; - NotifyChanged (TablePlacementChange.XOptions); + xOptions = value; + parent.ChildChanged (this, "XOptions"); } } - + public AttachOptions YOptions { - get { - return this.yOptions; - } + get { return yOptions; } set { - yOptions = value; - NotifyChanged (TablePlacementChange.YOptions); - } - } - - public int XPadding { - get { - return this.xPadding; - } - set { - xPadding = value; - NotifyChanged (TablePlacementChange.XPadding); - } - } - - public int YPadding { - get { - return this.yPadding; - } - set { - yPadding = value; - NotifyChanged (TablePlacementChange.YPadding); + yOptions = value; + parent.ChildChanged (this, "YOptions"); } } } + [Flags] public enum AttachOptions { - Shrink, - Expand, - Fill - }*/ + Expand = 1, + Fill = 2, + Shrink = 4 + } }