// PaletteSetWithCloseEvent.cs
// Copyright (c) 2009-2012 Tony Tanzillo
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
/// Abstract:
///
/// This class specializes the Autodesk.AutoCAD.Windows.PaletteSet
/// class, adding a PaletteSetClosed event along with a corresponding
/// overridable virtual method, allowing the PaletteSet and observers
/// of the event to be notified when the PaletteSet is closed.
///
/// Background:
///
/// The PaletteSet's StateChanged event fires multiple times when a
/// PaletteSet is docked, undocked, or rolled up when the Auto-hide
/// button is clicked. Because of that, it becomes impossible to use
/// that event directly to tell when a PaletteSet is actually hidden
/// (technically, PaletteSets are never 'closed', when the "x" close
/// button is clicked - rather they are hidden and remain in memory,
/// ready to be made visible again).
///
/// This class employs a few tricks to overcome this limitation, and
/// provides a new Event and overridable virtual method that signals
/// when the PalletSet is actually closed.
///
/// You can use this class in lieu of the stock PaletteSet class, if
/// you need to be notified when the PaletteSet is hidden. In all
/// other respects, it behaves exactly the same as its base class.
namespace Autodesk.AutoCAD.Windows
{
public class PaletteSetWithCloseEvent : PaletteSet
{
bool initialized = false;
public PaletteSetWithCloseEvent( string showCommand )
: base( showCommand )
{
Init();
}
public PaletteSetWithCloseEvent( string showCommand, Guid guid )
: base( showCommand, guid )
{
Init();
}
// Common construction operations.
// If you overload the constructor in a derived type,
// your overload must either supermessage one of the
// above constructors, or must call this method:
protected void Init()
{
if( ! initialized )
{
initialized = true;
this.StateChanged += stateChanged;
}
}
// Event to be fired on close.
// Note:
//
// If you derive your PaletteSet class from
// this class, then you should override the
// OnPaletteSetClosed() virtual method below,
// rather than handling this event. This event
// is primarily intended to be used from the
// outside, rather than from a derived type.
public event EventHandler PaletteSetClosed;
// flag indicating if Application.Idle is being handled
bool idleHandled = false;
// Flag indicating if the PaletteSet was rolled up when
// the StateChanged event fired:
bool wasRolledUp = false;
void stateChanged( object sender, PaletteSetStateEventArgs e )
{
if( ! idleHandled && e.NewState == StateEventIndex.Hide )
{
idleHandled = true;
this.wasRolledUp = base.RolledUp;
Application.Idle += onIdle;
}
else if( idleHandled && e.NewState == StateEventIndex.Show )
{
idleHandled = false;
Application.Idle -= onIdle;
}
}
// If the paletteset is docked/undocked or rolled-up,
// the idle event should not fire until the entire
// operation is completed, allowing it to be used to
// detect if the paletteSet is no longer visible:
// [TT] 08-12-12:
// Revised to deal with auto-hide, which was being
// mis-interpreted as closing the paletteset.
void onIdle( object sender, EventArgs e )
{
Application.Idle -= onIdle;
idleHandled = false;
if( ! ( base.Visible || ( wasRolledUp ^ this.RolledUp ) ) )
{
this.OnPaletteSetClosed();
}
}
// If you derive your PaletteSet class from this class (recommended),
// your derived class can override this method rather than handing
// the PaletteSetClosed event:
protected virtual void OnPaletteSetClosed()
{
if( this.PaletteSetClosed != null )
this.PaletteSetClosed( this, EventArgs.Empty );
}
}
}
// MyPaletteSet.cs - simple test case
//
// This simple test case also demonstrates the recommended
// pattern for consuming a PalletSet - by deriving a class from
// it that encapsulates all required functionality.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
namespace PaletteSetWithCloseEventTest
{
public class MyPaletteSet : PaletteSetWithCloseEvent
{
static MyPaletteSet instance = null;
static Guid guid
= new Guid
( "{41738157-3080-4015-AB53-3ACF8067C791}" ); const string showCommand = "MYPALETTESET";
public MyPaletteSet()
: base( showCommand, guid )
{
base.Add( "UserControl",
new System.Windows.Forms.UserControl() ); }
protected override void OnPaletteSetClosed()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
if( doc != null )
{
doc.Editor.WriteMessage( "\n*** OnPaletteSetClosed() - Without the kludge :p ***\n" );
}
}
[CommandMethod( showCommand )]
public static void MyPaletteSetCommand()
{
if( instance == null )
instance
= new MyPaletteSet
(); instance.Visible = true;
}
}
}