Infralution Support Forum Index Infralution Support
Support groups for Infralution products
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

UniversalEditBox in spanned row flickers

 
Post new topic   Reply to topic    Infralution Support Forum Index -> Virtual Tree Support
View previous topic :: View next topic  
Author Message
Mrdec



Joined: 04 May 2006
Posts: 7

PostPosted: Thu Apr 30, 2009 7:51 am    Post subject: UniversalEditBox in spanned row flickers Reply with quote

Hello,

I need to show a little button with ellipsis [...] in a spanned row and I want the button to be allways visible. So I created a UITypeEditor and assigned it to CellData (of the spanned row) and I also set CellData.DisplayMode to Always visible.

It works, but... when I'm clicking on rows (changing focused row) the editor in the spanned row flickers. It's because there is invoked the UniversalEditBox.OnLayout two-times. First with the width of the first column (bad) and for second with the width of the spanned row (good).

Is it possible to fix it? This is simple example, which demonstrates the situation:

Code:

public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
    Width = 250;
    Height = 300;

    // create tree
    VirtualTree tree = new VirtualTree();
    Controls.Add(tree);
    tree.Dock = DockStyle.Fill;
    tree.AutoFitColumns = true;

    // add two columns
    tree.Columns.Add(new Column());
    tree.Columns[0].Caption = "Name";
    tree.Columns.Add(new Column());
    tree.Columns[1].Caption = "Value";

    // binding for spanning row (to span root row)
    ObjectRowBinding stringBinding = new ObjectRowBinding(typeof(string));
    stringBinding.SpanningRow = true;
    tree.RowBindings.Add(stringBinding);

    // create editor
    UITypeEditor uiTypeEditor = new StandardValueEditor();
    UniversalEditBox universalEditBox = new UniversalEditBox();
    CellEditor cellEditor = new CellEditor(universalEditBox);
    cellEditor.DisplayMode = CellEditorDisplayMode.Always;

    // add handlers
    tree.GetChildren += delegate(object sender, GetChildrenEventArgs e)
    {
      if (e.Row.Item.ToString() == "root")
      {
        e.Children = new List<int>();
        for (int i = 0; i < 10; i++)
          e.Children.Add(i);
      }
    };

    tree.GetCellData += delegate(object sender, GetCellDataEventArgs e)
    {
      if (e.Column == tree.Columns[0])
      {
        e.CellData.Value = "name-" + e.Row.Item.ToString();
       
        // assign editor
        if (e.Row.Item.ToString() == "root")
        {
          e.CellData.Editor = cellEditor;
          e.CellData.TypeEditor = uiTypeEditor;
        }
      }
      else if (e.Column == tree.Columns[1])
        e.CellData.Value = "value-" + e.Row.Item.ToString();
    };

    // assign data source
    tree.DataSource = "root";
  }
}
Back to top
View user's profile Send private message
Mrdec



Joined: 04 May 2006
Posts: 7

PostPosted: Thu Apr 30, 2009 7:56 am    Post subject: UniversalEditBox in spanned row flickers Reply with quote

I'm using VirtualTree version 3.12.0.0.
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Thu Apr 30, 2009 10:50 pm    Post subject: Reply with quote

Thanks we will take a look at the issue and get back to you.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Mon May 04, 2009 12:38 am    Post subject: Reply with quote

The flicker is related to the way the SpanningWidget does layout. It calls the base RowWidget.OnLayout method to create the CellWidgets then adjusts CellWidget bounds. With some work it is possible to write the SpanningWidget.OnLayout method so that it does the layout from scratch and so doesn't have to call the base class OnLayout method.

We will include this modification in the next release (this may be a few weeks away since we have just released). In the meantime you can fix the issue by deriving your own custom SpanningWidget class and overriding the OnLayout method with the following code:

Code:
public class  MySpanningRowWidget : SpanningRowWidget
{

       public SpanningRowWidget(PanelWidget panelWidget, Row row)
            : base(panelWidget, row)
        {
        }

        private bool inLayout = false;

        public override void OnLayout()
        {
            Rectangle cellBounds = Bounds;
            ChildWidgets.Clear();

            // add the row header if any
            //
            if (ShowRowHeader)
            {
                cellBounds.Width = Tree.RowHeaderWidth;
                RowHeaderWidget.Bounds = RtlTranslateRect(cellBounds);
                ChildWidgets.Add(RowHeaderWidget);
                cellBounds.X += cellBounds.Width;
            }

            if (Columns.Contains(MainColumn))
            {
                Rectangle rowBounds = Bounds;
                int rowWidth = SpanningRowWidth;
                if (RightToLeft == RightToLeft.Yes)
                {
                    rowBounds.X += rowBounds.Width - rowWidth;
                }
                rowBounds.Width = rowWidth;
                if (!inLayout)
                {
                    inLayout = true;
                    Bounds = rowBounds;
                    inLayout = false;
                }
                if (this.RightToLeft == RightToLeft.Yes)
                {
                    cellBounds.Width = rowBounds.Width - (rowBounds.Right - cellBounds.Right);
                    cellBounds.X = rowBounds.X;
                }
                else
                {
                    cellBounds.Width = rowBounds.Width - cellBounds.X;
                }
                CellWidget cellWidget = GetCellWidget(MainColumn);
                cellWidget.Bounds = cellBounds;
                ChildWidgets.Add(cellWidget);

                // add the prefix cell widget if any
                //
                Column prefixColumn = Tree.PrefixColumn;
                if (RowData.ShowPrefixColumn && prefixColumn != null && prefixColumn.Visible)
                {
                    Rectangle prefixBounds = cellWidget.GetPrefixBounds(prefixColumn);

                    // check the widget is visible before adding it
                    //
                    if (prefixBounds.Width > 0)
                    {
                        CellWidget prefixWidget = GetCellWidget(prefixColumn);

                        // if both the cell editor and value are null then don't display
                        // the prefix
                        //
                        CellData cellData = prefixWidget.CellData;
                        if (cellData.Editor != null || cellData.Value != null)
                        {
                            prefixWidget.Bounds = prefixBounds;
                            ChildWidgets.Add(prefixWidget);

                            // set the width to reserve for the prefix widget
                            //
                            cellWidget.PrefixWidth = prefixBounds.Width;
                        }
                    }
                }
            }
        }
}


You then would need to override VirtualTree.CreateRowWidget (or set the RowWidgetCreator delegate) to return an instance of this RowWidget when the Row should be spanning.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Mrdec



Joined: 04 May 2006
Posts: 7

PostPosted: Mon May 04, 2009 10:51 am    Post subject: Still not perfect :-) Reply with quote

Thank you for your reply, it's much better, but it still flickers..
I used the MySpanningRowWidget in the example above and now it don't flicker because of Width, but it flickers because of Height. The OnLaout is still called two-times, ones with Bounds.Height = 18 and for second with Bounds.Height = 20. You can see it when you resize the form.
Back to top
View user's profile Send private message
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Mon May 04, 2009 10:29 pm    Post subject: Reply with quote

The OnLayout does get called twice (to handle auto fit height rows) but each time the bounds.height is set to 18. The problem is in this case that the editor control (a UniversalEditBox) has AutoSize set to true. This means that when VirtualTree attempts to set the height of the control to 18 it immediately resets to 20 (to fit the size font). There are two possible solutions:

1. Set UniversalEditBox.AutoSize to false.
2. Set CellEditor.UseCellHeight to false.

Both of these solutions eliminate the vertical flicker
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Mon May 04, 2009 11:09 pm    Post subject: Reply with quote

There was still an issue in the code I posted earlier which would show up if you pinned and unpinned the main column. The code below for the SpanningRowWidget.OnLayout fixes this:

Code:
        public override void OnLayout()
        {
            if (inLayout) return;
            inLayout = true;

            Rectangle cellBounds = Bounds;
            ChildWidgets.Clear();

            // add the row header if any
            //
            if (ShowRowHeader)
            {
                cellBounds.Width = Tree.RowHeaderWidth;
                RowHeaderWidget.Bounds = RtlTranslateRect(cellBounds);
                ChildWidgets.Add(RowHeaderWidget);
                cellBounds.X += cellBounds.Width;
            }

            if (Columns.Contains(MainColumn))
            {
                Rectangle rowBounds = Bounds;
                int rowWidth = SpanningRowWidth;
                if (RightToLeft == RightToLeft.Yes)
                {
                    rowBounds.X += rowBounds.Width - rowWidth;
                }
                rowBounds.Width = rowWidth;
                Bounds = rowBounds;
                if (this.RightToLeft == RightToLeft.Yes)
                {
                    cellBounds.Width = rowBounds.Width - (rowBounds.Right - cellBounds.Right);
                    cellBounds.X = rowBounds.X;
                }
                else
                {
                    cellBounds.Width = rowBounds.Width - cellBounds.X;
                }
                CellWidget cellWidget = GetCellWidget(MainColumn);
                cellWidget.Bounds = cellBounds;
                ChildWidgets.Add(cellWidget);

                // add the prefix cell widget if any
                //
                Column prefixColumn = Tree.PrefixColumn;
                if (RowData.ShowPrefixColumn && prefixColumn != null && prefixColumn.Visible)
                {
                    Rectangle prefixBounds = cellWidget.GetPrefixBounds(prefixColumn);

                    // check the widget is visible before adding it
                    //
                    if (prefixBounds.Width > 0)
                    {
                        CellWidget prefixWidget = GetCellWidget(prefixColumn);

                        // if both the cell editor and value are null then don't display
                        // the prefix
                        //
                        CellData cellData = prefixWidget.CellData;
                        if (cellData.Editor != null || cellData.Value != null)
                        {
                            prefixWidget.Bounds = prefixBounds;
                            ChildWidgets.Add(prefixWidget);

                            // set the width to reserve for the prefix widget
                            //
                            cellWidget.PrefixWidth = prefixBounds.Width;
                        }
                    }
                }
            }
            else
            {
                // Park widgets that are not active so that their editor (if any) is hidden
                //
                foreach (CellWidget cW in CellWidgets)
                {
                    cW.Bounds = Rectangle.Empty;
                }
            }
            inLayout = false;
        }   // OnLayout

_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Infralution



Joined: 28 Feb 2005
Posts: 5027

PostPosted: Tue May 12, 2009 4:23 am    Post subject: Reply with quote

Version 3.12.1 of Virtual Tree has now been released and incorporates this fix.
_________________
Infralution Support
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Infralution Support Forum Index -> Virtual Tree Support All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group