2 weeks ago
I made several applications with model dialogs but i strugle to understand the core functions for creating a modeless pallete. I saw posts from older AC version but i cant convert it to work with ac 28. DG_Test is far too complex for me to understand what's going on. Can anyone help me create basic dockable pallet which have close pallet and ok button. For ok button i want warning msg "it works" and that it from this point on i will probably figure it out. Also for now when i click on workspace with for example mep tool archicad crash. I cant close palette neither button works.
Solved! Go to Solution.
2 weeks ago
Based on i kinda figuret it out to get it work.
https://community.graphisoft.com/t5/Archicad-C-API/SOLVED-How-to-make-a-Palette-dialog-by-C-Class/m-...
Not sure if it is correct apporach becouse as far as i can see in DG_test menaging functionallity of buttons etc is diffrent then in this example above. Are there gonna be any troubles with this apporach in the future or can i stick with it?
a week ago
Here is a minimal implementation of a garbage collected palette. Using the DG_Test owner drawn listbox palette code as a template is not straightforward, as when the close button is pressed on it the palette instance will not be destroyed just get a hidden state and still continue to use system resources. With the following code the palette will be destroyed properly on a close interaction or call.
The resource looks like this:
'GDLG' DGTEST_MINIMALPALETTE_RESID Palette | grow | close 0 0 200 100 "Minimal Palette Example" {
/* [ 1] */ Button 110 70 80 24 LargePlain "Close"
/* [ 2] */ LeftText 4 4 192 60 LargePlain StaticEdge "This is a minimal DGPalette example dialog.\n\n"\
"The palette is visible only above the FloorPlan and the 3D Window."
}
'DLGH' DGTEST_MINIMALPALETTE_RESID Minimal_Palette_Example {
1 "Close Palette" CloseButton
2 "" InfoText
}
The resource contains a static control and a button only. I implemented it in the DG_Test addon source so the palette ID follows the convention of that addon.
In order the palette to be dockable it has the resizeable flag.
In the code there are 2 objects. The first is a singleton manager object which is publicly available. The other is the palette object that is accessible only through the manager object, therefore both of its declartion and the definition is in the cpp file.
The header file (MinimalPalette.hpp):
// =====================================================================================================================
// MinimalPalette.hpp
// =====================================================================================================================
#if !defined (MINIMALPALETTE_HPP)
#define MINIMALPALETTE_HPP
#pragma once
#include "ACAPinc.h"
#include "APIEnvir.h"
#include "DGModule.hpp"
#include "DisposableObject.hpp"
class MinimalPalette;
// === class MinimalPaletteManager =====================================================================================
class MinimalPaletteManager: public GS::DisposeHandler
{
private:
MinimalPalette* paletteInstance;
MinimalPaletteManager ();
MinimalPaletteManager (const MinimalPaletteManager& source) = delete;
MinimalPaletteManager operator= (const MinimalPaletteManager& source) = delete;
MinimalPalette& GetOrCreatePaletteInstance ();
virtual void DisposeRequested (GS::DisposableObject& source) override;
public:
virtual ~MinimalPaletteManager ();
static const GS::Guid& GetPaletteGuid ();
static Int32 GetPaletteRefId ();
static GSErrCode PaletteAPIControlCallBack (Int32 referenceID, API_PaletteMessageID messageID, GS::IntPtr param);
static MinimalPaletteManager& GetInstance ();
bool IsPaletteVisible () const;
void SetPaletteItemsStatus (bool enabled);
void ShowPalette ();
void ToggleVisibility ();
void ClosePalette ();
};
#endif // MINIMALPALETTE_HPP
The cpp file (MinimalPalette.cpp):
// =====================================================================================================================
// MinimalPalette.cpp
// =====================================================================================================================
#include "DGTestResIDs.hpp"
#include "DisposableObject.hpp"
#include "MinimalPalette.hpp"
// === MinimalPalette declaration=======================================================================================
class MinimalPalette: public DG::Palette,
public DG::PanelObserver,
public DG::ButtonItemObserver,
public GS::DisposableObject
{
private:
enum {
CloseButtonId = 1,
InfoTextId = 2
};
DG::Button closeButton;
DG::LeftText infoText;
MinimalPalette ();
protected:
virtual void PanelOpened (const DG::PanelOpenEvent& ev) override;
virtual void PanelCloseRequested (const DG::PanelCloseRequestEvent& ev, bool* accepted) override;
virtual void ButtonClicked (const DG::ButtonClickEvent& ev) override;
public:
MinimalPalette (const GS::Guid& paletteGuid);
virtual ~MinimalPalette ();
MinimalPalette (const MinimalPalette& source) = delete;
MinimalPalette operator= (const MinimalPalette& source) = delete;
void Close ();
};
// === MinimalPaletteManager Implementation ============================================================================
MinimalPaletteManager::MinimalPaletteManager ():
paletteInstance (nullptr)
{
}
MinimalPaletteManager::~MinimalPaletteManager ()
{
PRECOND (paletteInstance == nullptr);
}
MinimalPalette& MinimalPaletteManager::GetOrCreatePaletteInstance ()
{
if (paletteInstance == nullptr) {
paletteInstance = new MinimalPalette (GetPaletteGuid ());
}
return *paletteInstance;
}
void MinimalPaletteManager::DisposeRequested (GS::DisposableObject& source)
{
if (&source == paletteInstance) {
paletteInstance = nullptr;
}
}
const GS::Guid& MinimalPaletteManager::GetPaletteGuid ()
{
static GS::Guid guid ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); // Please generate a unique guid here!
return guid;
}
Int32 MinimalPaletteManager::GetPaletteRefId ()
{
static Int32 refId (GS::CalculateHashValue (GetPaletteGuid ()));
return refId;
}
GSErrCode MinimalPaletteManager::PaletteAPIControlCallBack (Int32 referenceID, API_PaletteMessageID messageID, GS::IntPtr param)
{
static bool paletteOpenAtClose = false;
GSErrCode err = NoError;
if (referenceID == MinimalPaletteManager::GetPaletteRefId ()) {
MinimalPaletteManager& paletteManager = MinimalPaletteManager::GetInstance ();
switch (messageID) {
case APIPalMsg_ClosePalette:
paletteManager.ClosePalette ();
break;
case APIPalMsg_HidePalette_Begin:
if (paletteManager.IsPaletteVisible ()) {
paletteOpenAtClose = true;
paletteManager.GetOrCreatePaletteInstance ().Hide ();
} else {
paletteOpenAtClose = false;
}
break;
case APIPalMsg_OpenPalette:
paletteOpenAtClose = true;
[[fallthrough]];
case APIPalMsg_HidePalette_End:
if (paletteOpenAtClose && !paletteManager.IsPaletteVisible ()) {
paletteManager.GetOrCreatePaletteInstance ().Show ();
}
break;
case APIPalMsg_DisableItems_Begin:
paletteManager.SetPaletteItemsStatus (false);
break;
case APIPalMsg_DisableItems_End:
paletteManager.SetPaletteItemsStatus (true);
break;
case APIPalMsg_IsPaletteVisible:
(*reinterpret_cast<bool*> (param)) = paletteManager.IsPaletteVisible ();
break;
default:
break;
}
}
return err;
}
MinimalPaletteManager& MinimalPaletteManager::GetInstance ()
{
static MinimalPaletteManager managerSingletonInstance;
return managerSingletonInstance;
}
bool MinimalPaletteManager::IsPaletteVisible () const
{
return paletteInstance != nullptr && paletteInstance->IsVisible ();
}
void MinimalPaletteManager::SetPaletteItemsStatus (bool enabled)
{
if (paletteInstance != nullptr) {
if (enabled) {
paletteInstance->EnableItems ();
} else {
paletteInstance->DisableItems ();
}
}
}
void MinimalPaletteManager::ShowPalette ()
{
GetOrCreatePaletteInstance ().Show ();
}
void MinimalPaletteManager::ToggleVisibility ()
{
if (IsPaletteVisible ()) {
ClosePalette ();
} else {
ShowPalette ();
}
}
void MinimalPaletteManager::ClosePalette ()
{
if (paletteInstance != nullptr) {
paletteInstance->Close ();
}
}
// === MinimalPalette implementation ===================================================================================
MinimalPalette::MinimalPalette (const GS::Guid& paletteGuid):
DG::Palette (ACAPI_GetOwnResModule (), DGTEST_MINIMALPALETTE_RESID, ACAPI_GetOwnResModule (), paletteGuid),
closeButton (GetReference (), CloseButtonId),
infoText (GetReference (), InfoTextId)
{
SetDefaultGarbageCollector ();
SetDisposeHandler (MinimalPaletteManager::GetInstance ());
AutoResizeBlock (infoText.HVGrow, closeButton.HVMove);
this->Attach (*this);
closeButton.Attach (*this);
this->BeginEventProcessing ();
}
MinimalPalette::~MinimalPalette ()
{
this->Detach (*this);
closeButton.Detach (*this);
}
void MinimalPalette::Close ()
{
SendCloseRequest ();
}
void MinimalPalette::PanelOpened (const DG::PanelOpenEvent& /*ev*/)
{
// if (ev.GetSource () != this) {
// return;
// }
// SetClientSize (GetOriginalClientWidth (), GetOriginalClientHeight ()); // Restores the size defined in the resource
}
void MinimalPalette::PanelCloseRequested (const DG::PanelCloseRequestEvent& ev, bool* /*accepted*/)
{
if (ev.GetSource () != this) {
return;
}
Hide ();
EndEventProcessing ();
MarkAsDisposable ();
}
void MinimalPalette::ButtonClicked (const DG::ButtonClickEvent& ev)
{
if (ev.GetSource () == &closeButton) {
Close ();
}
}
Some details about how it works:
The palette can be registered and unregistered with these calls:
ACAPI_RegisterModelessWindow (MinimalPaletteManager::GetPaletteRefId (),
MinimalPaletteManager::PaletteAPIControlCallBack,
API_PalEnabled_FloorPlan + API_PalEnabled_3D,
GSGuid2APIGuid (MinimalPaletteManager::GetPaletteGuid ()));
ACAPI_UnregisterModelessWindow (MinimalPaletteManager::GetPaletteRefId ());
Here the palette is set to be visible only above the FloorPlan and the 3D Window.
You can open and close the palette with these functions:
MinimalPaletteManager::GetInstance ().ShowPalette ();
MinimalPaletteManager::GetInstance ().ClosePalette ();
2 weeks ago
Based on i kinda figuret it out to get it work.
https://community.graphisoft.com/t5/Archicad-C-API/SOLVED-How-to-make-a-Palette-dialog-by-C-Class/m-...
Not sure if it is correct apporach becouse as far as i can see in DG_test menaging functionallity of buttons etc is diffrent then in this example above. Are there gonna be any troubles with this apporach in the future or can i stick with it?
a week ago
Here is a minimal implementation of a garbage collected palette. Using the DG_Test owner drawn listbox palette code as a template is not straightforward, as when the close button is pressed on it the palette instance will not be destroyed just get a hidden state and still continue to use system resources. With the following code the palette will be destroyed properly on a close interaction or call.
The resource looks like this:
'GDLG' DGTEST_MINIMALPALETTE_RESID Palette | grow | close 0 0 200 100 "Minimal Palette Example" {
/* [ 1] */ Button 110 70 80 24 LargePlain "Close"
/* [ 2] */ LeftText 4 4 192 60 LargePlain StaticEdge "This is a minimal DGPalette example dialog.\n\n"\
"The palette is visible only above the FloorPlan and the 3D Window."
}
'DLGH' DGTEST_MINIMALPALETTE_RESID Minimal_Palette_Example {
1 "Close Palette" CloseButton
2 "" InfoText
}
The resource contains a static control and a button only. I implemented it in the DG_Test addon source so the palette ID follows the convention of that addon.
In order the palette to be dockable it has the resizeable flag.
In the code there are 2 objects. The first is a singleton manager object which is publicly available. The other is the palette object that is accessible only through the manager object, therefore both of its declartion and the definition is in the cpp file.
The header file (MinimalPalette.hpp):
// =====================================================================================================================
// MinimalPalette.hpp
// =====================================================================================================================
#if !defined (MINIMALPALETTE_HPP)
#define MINIMALPALETTE_HPP
#pragma once
#include "ACAPinc.h"
#include "APIEnvir.h"
#include "DGModule.hpp"
#include "DisposableObject.hpp"
class MinimalPalette;
// === class MinimalPaletteManager =====================================================================================
class MinimalPaletteManager: public GS::DisposeHandler
{
private:
MinimalPalette* paletteInstance;
MinimalPaletteManager ();
MinimalPaletteManager (const MinimalPaletteManager& source) = delete;
MinimalPaletteManager operator= (const MinimalPaletteManager& source) = delete;
MinimalPalette& GetOrCreatePaletteInstance ();
virtual void DisposeRequested (GS::DisposableObject& source) override;
public:
virtual ~MinimalPaletteManager ();
static const GS::Guid& GetPaletteGuid ();
static Int32 GetPaletteRefId ();
static GSErrCode PaletteAPIControlCallBack (Int32 referenceID, API_PaletteMessageID messageID, GS::IntPtr param);
static MinimalPaletteManager& GetInstance ();
bool IsPaletteVisible () const;
void SetPaletteItemsStatus (bool enabled);
void ShowPalette ();
void ToggleVisibility ();
void ClosePalette ();
};
#endif // MINIMALPALETTE_HPP
The cpp file (MinimalPalette.cpp):
// =====================================================================================================================
// MinimalPalette.cpp
// =====================================================================================================================
#include "DGTestResIDs.hpp"
#include "DisposableObject.hpp"
#include "MinimalPalette.hpp"
// === MinimalPalette declaration=======================================================================================
class MinimalPalette: public DG::Palette,
public DG::PanelObserver,
public DG::ButtonItemObserver,
public GS::DisposableObject
{
private:
enum {
CloseButtonId = 1,
InfoTextId = 2
};
DG::Button closeButton;
DG::LeftText infoText;
MinimalPalette ();
protected:
virtual void PanelOpened (const DG::PanelOpenEvent& ev) override;
virtual void PanelCloseRequested (const DG::PanelCloseRequestEvent& ev, bool* accepted) override;
virtual void ButtonClicked (const DG::ButtonClickEvent& ev) override;
public:
MinimalPalette (const GS::Guid& paletteGuid);
virtual ~MinimalPalette ();
MinimalPalette (const MinimalPalette& source) = delete;
MinimalPalette operator= (const MinimalPalette& source) = delete;
void Close ();
};
// === MinimalPaletteManager Implementation ============================================================================
MinimalPaletteManager::MinimalPaletteManager ():
paletteInstance (nullptr)
{
}
MinimalPaletteManager::~MinimalPaletteManager ()
{
PRECOND (paletteInstance == nullptr);
}
MinimalPalette& MinimalPaletteManager::GetOrCreatePaletteInstance ()
{
if (paletteInstance == nullptr) {
paletteInstance = new MinimalPalette (GetPaletteGuid ());
}
return *paletteInstance;
}
void MinimalPaletteManager::DisposeRequested (GS::DisposableObject& source)
{
if (&source == paletteInstance) {
paletteInstance = nullptr;
}
}
const GS::Guid& MinimalPaletteManager::GetPaletteGuid ()
{
static GS::Guid guid ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); // Please generate a unique guid here!
return guid;
}
Int32 MinimalPaletteManager::GetPaletteRefId ()
{
static Int32 refId (GS::CalculateHashValue (GetPaletteGuid ()));
return refId;
}
GSErrCode MinimalPaletteManager::PaletteAPIControlCallBack (Int32 referenceID, API_PaletteMessageID messageID, GS::IntPtr param)
{
static bool paletteOpenAtClose = false;
GSErrCode err = NoError;
if (referenceID == MinimalPaletteManager::GetPaletteRefId ()) {
MinimalPaletteManager& paletteManager = MinimalPaletteManager::GetInstance ();
switch (messageID) {
case APIPalMsg_ClosePalette:
paletteManager.ClosePalette ();
break;
case APIPalMsg_HidePalette_Begin:
if (paletteManager.IsPaletteVisible ()) {
paletteOpenAtClose = true;
paletteManager.GetOrCreatePaletteInstance ().Hide ();
} else {
paletteOpenAtClose = false;
}
break;
case APIPalMsg_OpenPalette:
paletteOpenAtClose = true;
[[fallthrough]];
case APIPalMsg_HidePalette_End:
if (paletteOpenAtClose && !paletteManager.IsPaletteVisible ()) {
paletteManager.GetOrCreatePaletteInstance ().Show ();
}
break;
case APIPalMsg_DisableItems_Begin:
paletteManager.SetPaletteItemsStatus (false);
break;
case APIPalMsg_DisableItems_End:
paletteManager.SetPaletteItemsStatus (true);
break;
case APIPalMsg_IsPaletteVisible:
(*reinterpret_cast<bool*> (param)) = paletteManager.IsPaletteVisible ();
break;
default:
break;
}
}
return err;
}
MinimalPaletteManager& MinimalPaletteManager::GetInstance ()
{
static MinimalPaletteManager managerSingletonInstance;
return managerSingletonInstance;
}
bool MinimalPaletteManager::IsPaletteVisible () const
{
return paletteInstance != nullptr && paletteInstance->IsVisible ();
}
void MinimalPaletteManager::SetPaletteItemsStatus (bool enabled)
{
if (paletteInstance != nullptr) {
if (enabled) {
paletteInstance->EnableItems ();
} else {
paletteInstance->DisableItems ();
}
}
}
void MinimalPaletteManager::ShowPalette ()
{
GetOrCreatePaletteInstance ().Show ();
}
void MinimalPaletteManager::ToggleVisibility ()
{
if (IsPaletteVisible ()) {
ClosePalette ();
} else {
ShowPalette ();
}
}
void MinimalPaletteManager::ClosePalette ()
{
if (paletteInstance != nullptr) {
paletteInstance->Close ();
}
}
// === MinimalPalette implementation ===================================================================================
MinimalPalette::MinimalPalette (const GS::Guid& paletteGuid):
DG::Palette (ACAPI_GetOwnResModule (), DGTEST_MINIMALPALETTE_RESID, ACAPI_GetOwnResModule (), paletteGuid),
closeButton (GetReference (), CloseButtonId),
infoText (GetReference (), InfoTextId)
{
SetDefaultGarbageCollector ();
SetDisposeHandler (MinimalPaletteManager::GetInstance ());
AutoResizeBlock (infoText.HVGrow, closeButton.HVMove);
this->Attach (*this);
closeButton.Attach (*this);
this->BeginEventProcessing ();
}
MinimalPalette::~MinimalPalette ()
{
this->Detach (*this);
closeButton.Detach (*this);
}
void MinimalPalette::Close ()
{
SendCloseRequest ();
}
void MinimalPalette::PanelOpened (const DG::PanelOpenEvent& /*ev*/)
{
// if (ev.GetSource () != this) {
// return;
// }
// SetClientSize (GetOriginalClientWidth (), GetOriginalClientHeight ()); // Restores the size defined in the resource
}
void MinimalPalette::PanelCloseRequested (const DG::PanelCloseRequestEvent& ev, bool* /*accepted*/)
{
if (ev.GetSource () != this) {
return;
}
Hide ();
EndEventProcessing ();
MarkAsDisposable ();
}
void MinimalPalette::ButtonClicked (const DG::ButtonClickEvent& ev)
{
if (ev.GetSource () == &closeButton) {
Close ();
}
}
Some details about how it works:
The palette can be registered and unregistered with these calls:
ACAPI_RegisterModelessWindow (MinimalPaletteManager::GetPaletteRefId (),
MinimalPaletteManager::PaletteAPIControlCallBack,
API_PalEnabled_FloorPlan + API_PalEnabled_3D,
GSGuid2APIGuid (MinimalPaletteManager::GetPaletteGuid ()));
ACAPI_UnregisterModelessWindow (MinimalPaletteManager::GetPaletteRefId ());
Here the palette is set to be visible only above the FloorPlan and the 3D Window.
You can open and close the palette with these functions:
MinimalPaletteManager::GetInstance ().ShowPalette ();
MinimalPaletteManager::GetInstance ().ClosePalette ();