Author Topic: PaletteSet using CommandFlags.Session  (Read 2556 times)

0 Members and 1 Guest are viewing this topic.

WILL HATCH

  • Bull Frog
  • Posts: 448
PaletteSet using CommandFlags.Session
« on: May 20, 2013, 07:40:42 PM »
I've noticed a strange bug with my palette where once another document is opened up the user is able to open another instance of the palette.
Code - C#: [Select]
  1.     public class Commands
  2.     {
  3.         private PaletteSet _ps = null;
  4.  
  5.         private MyGrid _mg = null;
  6.         [CommandMethod("AXYZPalette", CommandFlags.Session)]
  7.         public void ShowTreePalette()
  8.         {
  9.             if (_ps == null)
  10.             {
  11.                 _ps = new PaletteSet("AXYZPalette", new Guid("45fb0c44-3ede-48c2-838e-98d742d1b4a9"));
  12.                 _ps.DockEnabled = DockSides.None | DockSides.Left | DockSides.Right;
  13.                 _ps.Size = new System.Drawing.Size(300, 500);
  14.             }
  15.             _ps.Visible = true;
  16.  
  17.             if (_mg == null)
  18.             {
  19.                 try
  20.                 {
  21.                     _mg = new MyGrid();
  22.                     ElementHost host = new ElementHost();
  23.                     host.AutoSize = true;
  24.                     host.Dock = DockStyle.Fill;
  25.                     host.Child = _mg;
  26.                     _ps.Add("TreeView", host);
  27.                 }
  28.                 catch (System.Exception e)
  29.                 {
  30.                     Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(String.Format("Error: {0}", e));
  31.                 }
  32.             }
  33.         }
  34.     }
This format of defining the new palette set seems to be pretty well standard, so I'm suspecting there is a collection somewhere of windows or something that I can look through to check if the palette is already open (or hidden) but not sure where to look.

Jeff_M

  • King Gator
  • Posts: 3948
  • C3D user & customizer
Re: PaletteSet using CommandFlags.Session
« Reply #1 on: May 20, 2013, 07:55:26 PM »
What we do is initialize the PaletteSets at load time, setting the visibility to false. Then any command that needs it just enables the visibility and toggles it back off when done.

TheMaster

  • Guest
Re: PaletteSet using CommandFlags.Session
« Reply #2 on: May 21, 2013, 12:37:51 AM »
I've noticed a strange bug with my palette where once another document is opened up the user is able to open another instance of the palette.
Code - C#: [Select]
  1.     public class Commands
  2.     {
  3.         private PaletteSet _ps = null;
  4.  
  5.         private MyGrid _mg = null;
  6.         [CommandMethod("AXYZPalette", CommandFlags.Session)]
  7.         public void ShowTreePalette()
  8.         {
  9.             if (_ps == null)
  10.             {
  11.                 _ps = new PaletteSet("AXYZPalette", new Guid("45fb0c44-3ede-48c2-838e-98d742d1b4a9"));
  12.                 _ps.DockEnabled = DockSides.None | DockSides.Left | DockSides.Right;
  13.                 _ps.Size = new System.Drawing.Size(300, 500);
  14.             }
  15.             _ps.Visible = true;
  16.  
  17.             if (_mg == null)
  18.             {
  19.                 try
  20.                 {
  21.                     _mg = new MyGrid();
  22.                     ElementHost host = new ElementHost();
  23.                     host.AutoSize = true;
  24.                     host.Dock = DockStyle.Fill;
  25.                     host.Child = _mg;
  26.                     _ps.Add("TreeView", host);
  27.                 }
  28.                 catch (System.Exception e)
  29.                 {
  30.                     Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(String.Format("Error: {0}", e));
  31.                 }
  32.             }
  33.         }
  34.     }
This format of defining the new palette set seems to be pretty well standard, so I'm suspecting there is a collection somewhere of windows or something that I can look through to check if the palette is already open (or hidden) but not sure where to look.

Your class and your command method are not static, which means that AutoCAD creates multiple instances of the class, one for each document the command is used in.  So, there are multiple instances of the class, along with any non-static members (like the PaletteSet member).

gile

  • Water Moccasin
  • Posts: 2234
  • Marseille, France
Re: PaletteSet using CommandFlags.Session
« Reply #3 on: May 21, 2013, 01:08:47 AM »
Hi,

By my side, I'd only set the PaletteSet and its control fields to static, I'd remove the 'CommandMethod' attribute from the ShowTreePalette() method and build a command (CommandFlags.Modal) in which the ShowTreePalette() is called.

Code - C#: [Select]
  1.     public class Commands
  2.     {
  3.         private static PaletteSet _ps = null;
  4.         private static MyGrid _mg = null;
  5.                    
  6.         public void ShowTreePalette()
  7.         {
  8.             if (_ps == null)
  9.             {
  10.                 _ps = new PaletteSet("AXYZPalette", new Guid("45fb0c44-3ede-48c2-838e-98d742d1b4a9"));
  11.                 _ps.DockEnabled = DockSides.None | DockSides.Left | DockSides.Right;
  12.                 _ps.Size = new System.Drawing.Size(300, 500);
  13.             }
  14.             _ps.Visible = true;
  15.  
  16.             if (_mg == null)
  17.             {
  18.                 try
  19.                 {
  20.                     _mg = new MyGrid();
  21.                     ElementHost host = new ElementHost();
  22.                     host.AutoSize = true;
  23.                     host.Dock = DockStyle.Fill;
  24.                     host.Child = _mg;
  25.                     _ps.Add("TreeView", host);
  26.                 }
  27.                 catch (System.Exception e)
  28.                 {
  29.                     Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(String.Format("Error: {0}", e));
  30.                 }
  31.             }
  32.         }
  33.                    
  34.         [CommandMethod("AXYZPalette",  CommandFlags.Modal)]
  35.         public static void AXYZPalette()
  36.         {
  37.                 this.ShowTreePalette();
  38.         }
  39.     }
« Last Edit: May 21, 2013, 01:28:34 AM by gile »
Speaking English as a French Frog

WILL HATCH

  • Bull Frog
  • Posts: 448
Re: PaletteSet using CommandFlags.Session
« Reply #4 on: May 21, 2013, 05:52:35 AM »
Thanks guys.  Interesting little bit of info for you:

@gile:
it is illegal to declare this.ShowTreePalette() from within a static method, easy enough fix but it raised the question to me of how does this really function so I added a few lines to show more about the inner workings:
Code - C#: [Select]
  1.     public class Commands
  2.     {
  3.         private static PaletteSet _ps = null;
  4.         private static MyGrid _mg = null;
  5.         private bool Initialized = false;
  6.         public void InitPalette()
  7.         {
  8.             try
  9.             {
  10.                 if (_ps == null)
  11.                 {
  12.                     _ps = new PaletteSet("AXYZPalette", new Guid("45fb0c44-3ede-48c2-838e-98d742d1b4a9"));
  13.                     _ps.DockEnabled = DockSides.None | DockSides.Left | DockSides.Right;
  14.                     _ps.Size = new System.Drawing.Size(600, 500);
  15.                 }
  16.                 _ps.Visible = true;
  17.                 if (_mg == null)
  18.                 {
  19.                     _mg = new MyGrid();
  20.                     ElementHost host = new ElementHost();
  21.                     host.AutoSize = true;
  22.                     host.Dock = DockStyle.Fill;
  23.                     host.Child = _mg;
  24.                     _ps.Add("TreeView", host);
  25.                 }
  26.  
  27.             }
  28.             catch (System.Exception ex)
  29.             {
  30.                 Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(String.Format("Error: {0}", ex));
  31.             }
  32.         }
  33.  
  34.  
  35.         [CommandMethod("AXYZPalette", CommandFlags.Modal)]
  36.         public void DisplayPalette()
  37.         {
  38.             Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(String.Format("_ps==null: {0}, Initialized: {1}", _ps==null , this.Initialized));
  39.             this.InitPalette();
  40.             this.Initialized = true;
  41.         }
  42.     }
on each new document opened if you run the AXYZPalette command the pop up tells us that Initialized == false so by not declaring the whole class as static we're reallocating memory for the non static portions (which might be useful in some cases) but for sheer simplicity I used Tony's approach in the final code.  This was a real palm face moment as I tried to make the class static before posting here but got the error "Static class cannot have instance members" and didn't realize that just meant declare the palette as static :ugly:
Code - C#: [Select]
  1.     public static class Commands
  2.     {
  3.         private static PaletteSet _ps = null;
  4.         private static MyGrid _mg = null;
  5.         [CommandMethod("AXYZPalette")]
  6.         public static void ShowPalette()
  7.         {
  8.             try
  9.             {
  10.                 if (_ps == null)
  11.                 {
  12.                     _ps = new PaletteSet("AXYZPalette", new Guid("45fb0c44-3ede-48c2-838e-98d742d1b4a9"));
  13.                     _ps.DockEnabled = DockSides.None | DockSides.Left | DockSides.Right;
  14.                     _ps.Size = new System.Drawing.Size(600, 500);
  15.                 }
  16.                 _ps.Visible = true;
  17.                 if (_mg == null)
  18.                 {
  19.                     _mg = new MyGrid();
  20.                     ElementHost host = new ElementHost();
  21.                     host.AutoSize = true;
  22.                     host.Dock = DockStyle.Fill;
  23.                     host.Child = _mg;
  24.                     _ps.Add("TreeView", host);
  25.                 }
  26.  
  27.             }
  28.             catch (System.Exception ex)
  29.             {
  30.                 Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(String.Format("Error: {0}", ex));
  31.             }
  32.         }
  33.     }

huiz

  • Swamp Rat
  • Posts: 853
  • Certified Prof C3D
Re: PaletteSet using CommandFlags.Session
« Reply #5 on: May 21, 2013, 08:53:34 AM »
You might consider using this:

Code: [Select]
_ps = new PaletteSet("AXYZPalette", "", new Guid("45fb0c44-3ede-48c2-838e-98d742d1b4a9"));

Mind the extra parameter in the middle. This way AutoCAD does not try to run a command named after your Palette. If you don't use the middle parameter then AutoCAD will run the command AXYZPalette, even if it is not created.
The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

kaefer

  • Swamp Rat
  • Posts: 572
Re: PaletteSet using CommandFlags.Session
« Reply #6 on: May 21, 2013, 11:52:01 AM »
Is that a singleton in your pocket or are you just happy to see me? A singleton with lazy initialization, that is.

Code - C#: [Select]
  1.     public static class Commands
  2.     {
  3.         private static Lazy<PaletteSet> ps = new Lazy<PaletteSet>(initPaletteSet);
  4.  
  5.         private static PaletteSet initPaletteSet()
  6.         {
  7.             return new PaletteSet("AXYZPalette", "", new Guid("45fb0c44-3ede-48c2-838e-98d742d1b4a9"))
  8.             {
  9.                 DockEnabled = DockSides.None | DockSides.Left | DockSides.Right,
  10.                 Size = new Size(600, 500)
  11.             };
  12.         }
  13.  
  14.         [CommandMethod("AXYZPalette")]
  15.         public static void ShowPalette()
  16.         {
  17.             ps.Value.Visible = true;
  18.         }
  19.     }


TheMaster

  • Guest
Re: PaletteSet using CommandFlags.Session
« Reply #7 on: May 21, 2013, 03:06:03 PM »
I rarely use the PaletteSet class directly.  I almost always derive a specialization from it and do whatever initialization needs to be done the constructor.  That also lets me override some virtual members, like the KeepFocus property.

See this example: http://www.theswamp.org/index.php?topic=42179.msg476706#msg476706