Archicad C++ API
About Archicad add-on development using the C++ API.

[SOLVED] How to make a Palette dialog by C++ Class

Anonymous
Not applicable
Hi there

This question already exist in forum but there are some functions which are not exist in DevKit 18 so please help.

Here is the code I'm using
Code:

//////////////////////////////////////////////////////////////////////// 
// Addon.cpp 


// --- Addon ------------------------------------------------------------ 

... 

#include "Palette.h" 

... 

GSErrCode __ACENV_CALL   Initialize (void) 
{ 
   GSErrCode err = NoError; 

   // Prevent the add-on auto-unloading 
        ACAPI_KeepInMemory(1); 

   // Install menu handler 
   err = ACAPI_Install_MenuHandler (32500, APIMenuCommandProc_32500); 

   ... 


   return err; 
}      /* Initialize */ 


GSErrCode __ACENV_CALL   FreeData (void) 
{ 
   ...    

   Palette::DeleteInstance(); 

   return NoError; 
}      /* FreeData */ 



GSErrCode __ACENV_CALL APIMenuCommandProc_32500 (const API_MenuParams *menuParams) 
{ 
   DBPrintf ("Test::APIMenuCommandProc_32500() %d/%d\n", menuParams->menuItemRef.menuResID, menuParams->menuItemRef.itemIndex); 
   ACAPI_KeepInMemory(1); 
   Palette::ToggleVisibility(); 
   return NoError; 
} 



//////////////////////////////////////////////////////////////////////// 
// Palette.h 

#pragma once; 

// --- Palette ------------------------------------------------------------ 

class Palette: public DG::Palette 
{ 
  friend class PaletteObserver; 

private: 
   static Palette* m_pPalette; 
  static PaletteObserver* m_pPaletteObserver; 

  enum { 
     CloseButtonId      = 1 
  }; 

DG::Button closeButton;  

private: 
  Palette(short resId); 

public: 
  ~Palette(); 
  void SelectionChanged(const API_Neig *selElemNeig); 


static Palette& GetInstance(); 
static bool HasInstance(); 
static void DeleteInstance(); 
static void ToggleVisibility(); 

}; 

// --- PaletteObserver ------------------------------------------------------------ 

class PaletteObserver: private DG::PanelObserver, 
  public  DG::ButtonItemObserver, 
  public  DG::CompoundItemObserver 
{ 
private: 
  Palette*   m_palette; 
public: 
  PaletteObserver (Palette* palette); 
  ~PaletteObserver(); 
  virtual void   SourceDestroyed (GS::EventSource* evSource); 
  virtual void   PanelOpened (const DG::PanelOpenEvent& ev); 
  virtual void   PanelCloseRequested (const DG::PanelCloseRequestEvent& ev, bool* accepted); 
  virtual void   PanelClosed (const DG::PanelCloseEvent& ev); 
  virtual void   PanelResized (const DG::PanelResizeEvent& ev); 
  virtual void   ButtonClicked (const DG::ButtonClickEvent& ev); 
}; 


//////////////////////////////////////////////////////////////////////// 
// Palette.cpp 

#if !defined (ACExtension) 
#define   ACExtension 
#endif 

#if defined (_MSC_VER) 
   #if !defined (WINDOWS) 
      #define WINDOWS 
   #endif 
#endif 

#if defined (WINDOWS) 
   #include "Win32Interface.hpp" 
   #pragma warning (disable: 4068) 
#endif 

// ------------------------------ Includes ------------------------------------- 

#include   <stdio.h> 
#include   <math.h> 
#include   <string.h> 

#if defined (macintosh) 
#include   <MacTypes.h> 
#endif 

#include   "DG.h" 
#include   "DGModule.hpp" 

#include   "ACAPinc.h" 
#include   "APICommon.h"   // also includes GSRoot.hpp 


#include "Palette.h" 

static GS::Guid   PaletteGuid  ("{9597C98D-95BD-48d9-9999-C2297834806B}"); 

static GSErrCode __ACENV_CALL   ModelessWindowCallBack (long referenceID, API_PaletteMessageID messageID) 
{ 
   if (Palette::HasInstance() && referenceID == Palette::GetInstance().GetId()) { 
      switch (messageID) { 
      case APIPalMsg_ClosePalette:    
          Palette::GetInstance().SendCloseRequest();  
         break; 
      case APIPalMsg_HidePalette_Begin:    
         break; 
      case APIPalMsg_HidePalette_End:    
         break; 
      case APIPalMsg_DisableItems_Begin:    
         break; 
      case APIPalMsg_DisableItems_End:    
               break; 
     } 
   } 
   return NoError; 
} 

// --- Palette ------------------------------------------------------------ 

/*static*/ Palette* Palette::m_pPalette = NULL; 
/*static*/ PaletteObserver* Palette::m_pPaletteObserver = NULL; 

/////////////////////////////////////////// 

/*static*/ Palette& Palette::GetInstance() 
{ 
   if (!m_pPalette) { 
     GSResModule actResModule = ACAPI_UseOwnResModule (); 
      m_pPalette = new Palette(32420);  
     ACAPI_ResetResModule (actResModule); 
       m_pPaletteObserver = new PaletteObserver(m_pPalette); 
   } 
   return *m_pPalette; 
} 

/*static*/ bool Palette::HasInstance() 
{ 
   return m_pPalette != NULL; 
} 

/*static*/ void Palette::DeleteInstance() 
{ 
   DBASSERT(m_pPalette != NULL); 
   if (m_pPalette != NULL) { 
      delete m_pPalette; 
      m_pPalette = NULL; 
   } 
   if (m_pPaletteObserver != NULL) { 
      delete m_pPaletteObserver; 
      m_pPaletteObserver = NULL; 
   } 
} 

/*static*/ void Palette::ToggleVisibility() { 
   if (m_pPalette != NULL && m_pPalette->IsVisible()) { 
      m_pPalette->EndEventProcessing(); 
      m_pPalette->Hide(); 
   } else { 
          Palette::GetInstance().BeginEventProcessing(); 
          m_pPalette->Show(); 
   } 
} 

////////////////////////////////////////////////////////// 

Palette::Palette(short resId) : DG::Palette(resId, PaletteGuid), 
 closeButton (GetReference (), CloseButtonId) 
{ 
   ACAPI_RegisterModelessWindow (GetId(), ModelessWindowCallBack, 
          API_PalEnabled_FloorPlan + 
               API_PalEnabled_Section + 
               API_PalEnabled_Detail + 
               API_PalEnabled_Layout + 
               API_PalEnabled_3D 
    ); 
} 


Palette::~Palette () 
{ 
   ACAPI_UnregisterModelessWindow (GetId()); 
} 

void Palette::SelectionChanged(const API_Neig *selElemNeig) 
{ 
  if (selElemNeig->neigID != APINeig_None) 
   { 
      DBPrintf("Last selected element: NeigID %d; guid: %s, inIndex: %d\n", 
               selElemNeig->neigID, (const char *) APIGuid2GSGuid (selElemNeig->guid).ToUniString ().ToCStr (), 
               selElemNeig->inIndex); 
         closeButton.Enable(); 
   } else { 
      DBPrintf("All elements deselected\n"); 
         closeButton.Disable(); 
   } 
} 





// --- PaletteObserver ------------------------------------------------------------ 

PaletteObserver::PaletteObserver (Palette* palette) 
: m_palette (palette) 
{ 
   if (DBVERIFY (m_palette != NULL)) { 
      palette->Attach (*this); 
      AttachToAllItems (*m_palette); 
   } 
} 


PaletteObserver::~PaletteObserver () 
{ 
   if (m_palette != NULL) { 
      m_palette->Detach (*this); 
      DetachFromAllItems (*m_palette); 
   } 
} 


// ... Public methods .......................................................... 

void PaletteObserver::SourceDestroyed (GS::EventSource* evSource) 
{ 
   if (evSource == m_palette) { 
      //MarkAsFinished (); 
      //notesObserver->FindPaletteDestroyed (); 
      //palette = NULL; 
   } 
} 


// ... Dialog notifications .................................................... 

void PaletteObserver::PanelOpened (const DG::PanelOpenEvent& /*ev*/) 
{ 
   SetMenuItemMark(32500, 1, true); 

   /*palette->findEdit.SetText (palette->findData->findText); 
   palette->replaceEdit.SetText (palette->findData->replaceText); 
   FindValidate (); 

   if (palette->findData->findWholeWord) 
      palette->wholeWordCheck.Check (); 
   if (palette->findData->findMatchCase) 
      palette->matchCaseCheck.Check (); 
   if (palette->findData->findWrap) 
      palette->wrapCheck.Check (); 

   if (palette->findData->findUp) 
      palette->upRadio.Select (); 
   else 
      palette->downRadio.Select (); 

   palette->findEdit.SetFocus ();*/ 
} 


void PaletteObserver::PanelCloseRequested (const DG::PanelCloseRequestEvent& /*ev*/, bool* /*accepted*/) 
{ 
   m_palette->EndEventProcessing (); 
} 

void PaletteObserver::PanelClosed (const DG::PanelCloseEvent& /*ev*/) 
{ 
   SetMenuItemMark(32500, 1, false); 
} 

void PaletteObserver::PanelResized (const DG::PanelResizeEvent& ev) 
{ 
   short dh = ev.GetHorizontalChange (); 
   short dv = ev.GetVerticalChange (); 

   m_palette->BeginMoveResizeItems(); 

   //dialog->separator.Move (dh, 0); 

   m_palette->closeButton.Move (dh, dv); 

   m_palette->EndMoveResizeItems(); 
} 

// ... Dialog item notifications ............................................... 

void   PaletteObserver::ButtonClicked (const DG::ButtonClickEvent& ev) 
{ 
   if (ev.GetSource () == &m_palette->closeButton) { 
      m_palette->SendCloseRequest (); 
   } 
} 

And here is the errors

error C3861: 'ACAPI_UseOwnResModule': identifier not found
error C3861: 'ACAPI_ResetResModule': identifier not found
error C2664: 'DG::Palette::Palette(const DG::Rect &,DG::Dialog::GrowType,DG::Dialog::CloseType,DG::Dialog::CaptionType,DG::Dialog::FrameType,DG::Dialog::SpecialFeatures)' : cannot convert parameter 1 from 'short' to 'const DG::Rect &'
Reason: cannot convert from 'short' to 'const DG::Rect'
5 REPLIES 5
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Hi,

you can read about this in the API DevKit documentation's "New API features in ArchiCAD 18" topic:
Resource chain is gone (also ACAPI_UseOwnResModule() and ACAPI_ResetResModule() along with it)
OS X internally maintained a stack of open resource files called the resource chain. Whenever you want to load a resource, the system searched downwards in this stack to find the resource in any of the open resource files below the current one.
We removed that implicit mechanism; you'll have to specify each and every time the resource module explicitly (usually with ACAPI_GetOwnResModule()).
So you should remove all of your ACAPI_UseOwnResModule() and ACAPI_ResetResModule() calls and then that problem will be solved

Constructor of DG::Palette has been changed (and all of other DG constructors too). Now you should use ACAPI_GetOwnResModule() when calling that constructor.
So please change this line in your code:
Palette::Palette(short resId) : DG::Palette(resId, PaletteGuid),
to this:
Palette::Palette(short resId) : DG::Palette(ACAPI_GetOwnResModule(), resId, ACAPI_GetOwnResModule(), PaletteGuid),
(You can find DG::Palette::Palette constructor in DGDialog.hpp header file.)

Regards,
Tibor
Anonymous
Not applicable
Thank you for the help.

Still I have question.

I tried to read documentation. But in documentation's example again with old methods which is not supported by DevKit18. Please kindly give me a small example. So I can understand how to do that with C++ class.
Tibor Lorantfy
Graphisoft Alumni
Graphisoft Alumni
Today I implemented an example palette for you.
Note that this is a minimal example, just to show how to make custom C++ Palette class properly.

GRC
/* Text appearing in the menu */  
  
'STR#' 32500 "Menu strings" {  
/* [   ] */		"Test"  
/* [   ] */		"DG Functions"  
/* [  1] */			"Open Example Palette"  
}  
  
'STR#' 32520 "Prompt strings" {  
/* [   ] */		"Test"  
/* [   ] */		"DG Functions"  
/* [  1] */			"Open Example Palette"  
}  
  
/* ---------------------------------------------------------- Example Palette */  
  
'GDLG'  32590  Palette | hGrow | close	    0    0  160   40  "Test Palette" {  
/* [  1] */ Button					 10   10  140   20	LargePlain  "Hide"  
}  
  
'DLGH'  32590  DLG_32580_Test_Palette {  
1	""					Button_0  
}
ExamplePalette.hpp
// ---------------------------------- Includes ---------------------------------  
  
#include "APIEnvir.h"  
#include	"ACAPinc.h"  
#include	"DG.h"  
#include	"DGModule.hpp"  
  
#include	"DisposableObject.hpp"  
  
  
#define EXAMPLEPALETTE_RESID		32590  
  
// --- ExamplePalette ----------------------------------------------------------  
  
class ExamplePalette:	public	DG::Palette,  
				public	DG::PanelObserver,  
				public	DG::ButtonItemObserver,  
				public	DG::CompoundItemObserver,  
				public	GS::DisposableObject  
{  
private:
	enum {  
		HideButtonId		= 1  
	};  
  
	DG::Button		hideButton;  
  
	ExamplePalette	(GSResModule dialResModule, short resId);  
  
protected:  
	virtual void	PanelOpened		(const DG::PanelOpenEvent& ev) override;  
	virtual void	PanelResized		(const DG::PanelResizeEvent& ev) override;  
	virtual void	PanelCloseRequested	(const DG::PanelCloseRequestEvent& ev, bool* accept) override;  
  
	virtual void	ButtonClicked		(const DG::ButtonClickEvent& ev) override;  
  
public:  
	static const GS::Guid		paletteGuid;  
	static Int32			paletteRefId;  
  
	ExamplePalette		();  
	~ExamplePalette	();  
  
	static GSErrCode __ACENV_CALL	PaletteAPIControlCallBack (Int32 referenceID, API_PaletteMessageID messageID, GS::IntPtr param);  
};  
  
  
// --- ExamplePaletteManager ---------------------------------------------------  
  
class ExamplePaletteManager	:	public	GS::DisposeHandler  
{  
private:  
	ExamplePalette*	examplePalette;  
  
	ExamplePaletteManager	();  
	ExamplePaletteManager	(const ExamplePaletteManager& source);	//disabled

	ExamplePaletteManager	operator=	(const ExamplePaletteManager& source);	//disabled  
  
public:  
	~ExamplePaletteManager					();  
  
	static ExamplePaletteManager&	GetInstance	();  
  
	static void		OpenExamplePalette			();  
	static void		CloseExamplePalette			();  
	static bool		IsExamplePaletteOpened		();  
  
	ExamplePalette* GetExamplePalette			();  
  
	virtual void	DisposeRequested		(GS::DisposableObject& source) override;  
};


ExamplePalette.cpp
// ---------------------------------- Includes ---------------------------------  
  
#include	"ExamplePalette.hpp"
  
//------------------------------ Class ExamplePalette --------------------------  
  
const GS::Guid	ExamplePalette::paletteGuid ("{D8A0A01F-1184-40F2-B8A8-28CF30714FA4}");  
Int32		ExamplePalette::paletteRefId = (Int32) GS::GenerateHashValue (ExamplePalette::paletteGuid);  
  
  
ExamplePalette::ExamplePalette ():  
	DG::Palette	(ACAPI_GetOwnResModule (), EXAMPLEPALETTE_RESID, ACAPI_GetOwnResModule (), paletteGuid),  
  
	hideButton	(GetReference (), HideButtonId)  
{  
	Attach (*this);  
	AttachToAllItems (*this);  
  
	SetDefaultGarbageCollector ();  
	SetDisposeHandler (ExamplePaletteManager::GetInstance ());  
}  
  
  
ExamplePalette::~ExamplePalette ()  
{  
	Detach (*this);  
	DetachFromAllItems (*this);
}  
  
  
void ExamplePalette::PanelOpened (const DG::PanelOpenEvent& /*ev*/)  
{  
}  
  
  
void ExamplePalette::PanelResized (const DG::PanelResizeEvent& ev)  
{  
	short vGrow = ev.GetVerticalChange ();  
	short hGrow = ev.GetHorizontalChange ();  
  
	if (vGrow != 0 || hGrow != 0) {  
		BeginMoveResizeItems ();  
  
		hideButton.Move (hGrow, vGrow);  
  
		EndMoveResizeItems ();  
	}  
}  
  
  
void ExamplePalette::PanelCloseRequested (const DG::PanelCloseRequestEvent& ev, bool* /*accept*/)  
{  
	if (ev.GetSource () != this)  
		return;  
  
	Hide				();  
	EndEventProcessing	();  
	MarkAsDisposable	();  
}  
  
  
void ExamplePalette::ButtonClicked (const DG::ButtonClickEvent& ev)  
{  
	if (ev.GetSource () == &hideButton) {  
		Hide ();  
	}  
}  
  
  
GSErrCode __ACENV_CALL	ExamplePalette::PaletteAPIControlCallBack (Int32 referenceID, API_PaletteMessageID messageID, GS::IntPtr param)  
{  
	GSErrCode	err = NoError;  
  
	if (referenceID == paletteRefId) {  
		switch (messageID) {  
			case APIPalMsg_OpenPalette:  
				ExamplePaletteManager::OpenExamplePalette ();  
				break;  
  
			case APIPalMsg_ClosePalette:  
				ExamplePaletteManager::CloseExamplePalette ();  
				break;  
  
			case APIPalMsg_HidePalette_Begin:  
				if (ExamplePaletteManager::IsExamplePaletteOpened ())  
					ExamplePaletteManager::GetInstance ().GetExamplePalette ()->Hide ();  
				break;  
  
			case APIPalMsg_HidePalette_End:  
				if (ExamplePaletteManager::IsExamplePaletteOpened ())  
					ExamplePaletteManager::GetInstance ().GetExamplePalette ()->Show ();  
				break;  
  
			case APIPalMsg_DisableItems_Begin:  
				if (ExamplePaletteManager::IsExamplePaletteOpened ())  
					ExamplePaletteManager::GetInstance ().GetExamplePalette ()->DisableItems ();  
				break;  
  
			case APIPalMsg_DisableItems_End:  
				if (ExamplePaletteManager::IsExamplePaletteOpened ())  
					ExamplePaletteManager::GetInstance ().GetExamplePalette ()->EnableItems ();  
				break;  
  
			case APIPalMsg_IsPaletteVisible:  
				*(reinterpret_cast<bool*> (param)) = (ExamplePaletteManager::IsExamplePaletteOpened () && ExamplePaletteManager::GetInstance ().GetExamplePalette ()->IsVisible ());  
				break;  
  
			default:  
				break;  
		}  
	}  
  
	return err;  
}  
  
  
//-------------------------- Class ExamplePaletteManager -----------------------  
  
ExamplePaletteManager&	ExamplePaletteManager::GetInstance	()  
{  
	static ExamplePaletteManager instance;  
  
	return instance;  
}  
  
  
ExamplePaletteManager::ExamplePaletteManager () :  
	examplePalette (NULL)  
{  
}  
  
  
ExamplePaletteManager::~ExamplePaletteManager ()  
{  
	if (DBERROR (examplePalette != NULL)) {  
		examplePalette->EndEventProcessing ();  
		delete examplePalette;  
		examplePalette = NULL;  
	}  
}  
  
  
void	ExamplePaletteManager::OpenExamplePalette ()  
{  
	ExamplePaletteManager& manager = GetInstance ();  
  
	if (manager.examplePalette == NULL) {  
		manager.examplePalette = new ExamplePalette ();  
		if (DBERROR (manager.examplePalette == NULL))  
			return;  
	}  
  
	manager.examplePalette->BeginEventProcessing ();  
	manager.examplePalette->Show ();  
}  
  
  
void	ExamplePaletteManager::CloseExamplePalette ()  
{  
	ExamplePaletteManager& manager = GetInstance ();  
  
	if (manager.examplePalette == NULL)  
		return;  
  
	manager.examplePalette->Hide ();  
	manager.examplePalette->EndEventProcessing ();  
	delete manager.examplePalette;  
	manager.examplePalette = NULL;  
}  
  
  
bool	ExamplePaletteManager::IsExamplePaletteOpened (void)  
{  
	return GetInstance ().examplePalette != NULL;  
}  
  
  
void	ExamplePaletteManager::DisposeRequested (GS::DisposableObject& source)  
{  
	ExamplePaletteManager& manager = GetInstance ();  
	if (&source == manager.examplePalette) {  
		manager.examplePalette = NULL;  
	}  
}  
  
  
ExamplePalette* ExamplePaletteManager::GetExamplePalette ()  
{  
	return this->examplePalette;  
}
Main.cpp
// ---------------------------------- Includes ---------------------------------

#include "APIEnvir.h"
#include	"ACAPinc.h"
#include	"APICommon.h"

#include	"ExamplePalette.hpp"

// -----------------------------------------------------------------------------
// Function to open the Example Palette
// -----------------------------------------------------------------------------

static void		Open_ExamplePalette (void)
{
	if (!ExamplePaletteManager::IsExamplePaletteOpened ())
		ExamplePaletteManager::OpenExamplePalette ();
	return;
}


// -----------------------------------------------------------------------------
// Handles menu commands
// -----------------------------------------------------------------------------

GSErrCode __ACENV_CALL MenuCommandHandler (const API_MenuParams *menuParams)
{
	switch (menuParams->menuItemRef.menuResID) {
		case 32500:
			switch (menuParams->menuItemRef.itemIndex) {
				case 1:	Open_ExamplePalette ();				break;
			}
			break;
	}

	return NoError;
}		// MenuCommandHandler


// -----------------------------------------------------------------------------
// Interface definitions
// -----------------------------------------------------------------------------

GSErrCode	__ACENV_CALL	RegisterInterface (void)
{
	GSErrCode err;

	err = ACAPI_Register_Menu (32500, 32520, MenuCode_UserDef, MenuFlag_Default);
	if (err != NoError)
		DBPrintf ("DG_Test:: RegisterInterface() ACAPI_Register_Menu failed\n");

	return err;
}		// RegisterInterface


// -----------------------------------------------------------------------------
// Called when the Add-On has been loaded into memory
// to perform an operation
// -----------------------------------------------------------------------------

GSErrCode	__ACENV_CALL Initialize	(void)
{
	GSErrCode err = ACAPI_Install_MenuHandler (32500, MenuCommandHandler);
	if (err != NoError)
		DBPrintf ("DG_Test:: Initialize() ACAPI_Install_MenuHandler failed\n");

	err = ACAPI_RegisterModelessWindow (ExamplePalette::paletteRefId, ExamplePalette::PaletteAPIControlCallBack,
										API_PalEnabled_FloorPlan + API_PalEnabled_3D + API_PalEnabled_Layout,
										GSGuid2APIGuid (ExamplePalette::paletteGuid));
	if (err != NoError)
		DBPrintf ("DG_Test:: Initialize() ACAPI_RegisterModelessWindow failed\n");

	return err;
}		// Initialize


// -----------------------------------------------------------------------------
// FreeData
//		called when the Add-On is going to be unloaded
// -----------------------------------------------------------------------------

GSErrCode __ACENV_CALL	FreeData (void)
{
	ACAPI_UnregisterModelessWindow (ExamplePalette::paletteRefId);

	return NoError;
}		// FreeData
Anonymous
Not applicable
Thank you very much.
This is what I need.

nice