Merge pull request #7 from specklesystems/david/cnx-150-implement-selectionbinding
David/cnx 150 implement selectionbinding
This commit is contained in:
@@ -111,6 +111,9 @@
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\GetConfig.cpp" />
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\GetIsDevMode.cpp" />
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\UpdateConfig.cpp" />
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Selection\Arg\SelectionInfo.cpp" />
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Selection\GetSelection.cpp" />
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Selection\SelectionBridge.cpp" />
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\ConversionResult.cpp" />
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendError.cpp" />
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendObject.cpp" />
|
||||
@@ -163,6 +166,9 @@
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\GetConfig.h" />
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\GetIsDevMode.h" />
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\UpdateConfig.h" />
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Selection\Arg\SelectionInfo.h" />
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Selection\GetSelection.h" />
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Selection\SelectionBridge.h" />
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\ConversionResult.h" />
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendError.h" />
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendObject.h" />
|
||||
|
||||
@@ -65,6 +65,12 @@
|
||||
<Filter Include="Connector\Interface\Browser\Bridge\Send\Arg">
|
||||
<UniqueIdentifier>{6693f9a9-5ece-4853-b008-4064d1c551ab}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Connector\Interface\Browser\Bridge\Selection">
|
||||
<UniqueIdentifier>{806f4af5-fa02-49b8-ac01-297991fe90ea}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Connector\Interface\Browser\Bridge\Selection\Arg">
|
||||
<UniqueIdentifier>{8bb3df60-affe-4b66-8d78-f1b98e6ba8df}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="RFIX.win\Connector.rc2">
|
||||
@@ -228,6 +234,15 @@
|
||||
<ClCompile Include="Connector\Record\Collection\ProjectCollection.cpp">
|
||||
<Filter>Connector\Record\Collection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Selection\GetSelection.cpp">
|
||||
<Filter>Connector\Interface\Browser\Bridge\Selection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Selection\SelectionBridge.cpp">
|
||||
<Filter>Connector\Interface\Browser\Bridge\Selection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Connector\Interface\Browser\Bridge\Selection\Arg\SelectionInfo.cpp">
|
||||
<Filter>Connector\Interface\Browser\Bridge\Selection\Arg</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Connector\ConnectorResource.h">
|
||||
@@ -387,5 +402,14 @@
|
||||
<ClInclude Include="Connector\Record\Collection\ProjectCollection.h">
|
||||
<Filter>Connector\Record\Collection</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Selection\GetSelection.h">
|
||||
<Filter>Connector\Interface\Browser\Bridge\Selection</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Selection\SelectionBridge.h">
|
||||
<Filter>Connector\Interface\Browser\Bridge\Selection</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Connector\Interface\Browser\Bridge\Selection\Arg\SelectionInfo.h">
|
||||
<Filter>Connector\Interface\Browser\Bridge\Selection\Arg</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
|
||||
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
|
||||
#include "Connector/Connector.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h"
|
||||
#include "Speckle/Database/BIMElementDatabase.h"
|
||||
#include "Speckle/Environment/Project.h"
|
||||
#include "Speckle/Record/Element/Element.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace connector::interfac::browser::bridge;
|
||||
using namespace speckle::record::element;
|
||||
|
||||
namespace {
|
||||
|
||||
///Serialisation fields
|
||||
enum FieldIndex {
|
||||
selectedObjectIdsID,
|
||||
summaryID,
|
||||
};
|
||||
|
||||
///Serialisation field IDs
|
||||
static std::array fieldID = {
|
||||
Identity{"selectedObjectIds"},
|
||||
Identity{"summary"},
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
SelectionInfo::SelectionInfo() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void SelectionInfo::initialize() {
|
||||
auto project = connector()->getActiveProject().lock();
|
||||
if (!project) {
|
||||
// TODO: is thi OK?
|
||||
return;
|
||||
}
|
||||
|
||||
auto elementDatabase = project->getElementDatabase();
|
||||
auto selected = elementDatabase->getSelection();
|
||||
|
||||
active::utility::String summary(selected.size());
|
||||
summary += " objects selected.";
|
||||
m_summary = summary;
|
||||
|
||||
for (const auto& link : selected) {
|
||||
m_selectedElementIds.push_back(link);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Fill an inventory with the package items
|
||||
|
||||
inventory: The inventory to receive the package items
|
||||
|
||||
return: True if the package has added items to the inventory
|
||||
--------------------------------------------------------------------*/
|
||||
bool SelectionInfo::fillInventory(Inventory& inventory) const {
|
||||
using enum Entry::Type;
|
||||
inventory.merge(Inventory{
|
||||
{
|
||||
{ fieldID[selectedObjectIdsID], selectedObjectIdsID, element },
|
||||
{ fieldID[summaryID], summaryID, element },
|
||||
},
|
||||
}.withType(&typeid(SelectionInfo)));
|
||||
return true;
|
||||
} //SelectionInfo::fillInventory
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get the specified cargo
|
||||
|
||||
item: The inventory item to retrieve
|
||||
|
||||
return: The requested cargo (nullptr on failure)
|
||||
--------------------------------------------------------------------*/
|
||||
Cargo::Unique SelectionInfo::getCargo(const Inventory::Item& item) const {
|
||||
if (item.ownerType != &typeid(SelectionInfo))
|
||||
return nullptr;
|
||||
using namespace active::serialise;
|
||||
switch (item.index) {
|
||||
case selectedObjectIdsID:
|
||||
return std::make_unique<ContainerWrap<std::vector<active::utility::Guid>>>(m_selectedElementIds);
|
||||
case summaryID:
|
||||
return std::make_unique<ValueWrap<active::utility::String>>(m_summary);
|
||||
default:
|
||||
return nullptr; //Requested an unknown index
|
||||
}
|
||||
} //SelectionInfo::getCargo
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef CONNECTOR_INTERFACE_BRIDGE_SELECTION_INFO
|
||||
#define CONNECTOR_INTERFACE_BRIDGE_SELECTION_INFO
|
||||
|
||||
#include "Active/Serialise/Package/Package.h"
|
||||
|
||||
namespace connector::interfac::browser::bridge {
|
||||
|
||||
/*!
|
||||
Configuration settings class
|
||||
*/
|
||||
class SelectionInfo : public active::serialise::Package {
|
||||
public:
|
||||
|
||||
// MARK: - Types
|
||||
|
||||
using base = active::serialise::Package;
|
||||
|
||||
// MARK: - Constructors
|
||||
|
||||
/*!
|
||||
Default constructor
|
||||
*/
|
||||
SelectionInfo();
|
||||
|
||||
active::utility::String m_summary = "No objects selected";
|
||||
std::vector<active::utility::Guid> m_selectedElementIds;
|
||||
|
||||
// MARK: - Serialisation
|
||||
|
||||
/*!
|
||||
Fill an inventory with the package items
|
||||
@param inventory The inventory to receive the package items
|
||||
@return True if the package has added items to the inventory
|
||||
*/
|
||||
bool fillInventory(active::serialise::Inventory& inventory) const override;
|
||||
/*!
|
||||
Get the specified cargo
|
||||
@param item The inventory item to retrieve
|
||||
@return The requested cargo (nullptr on failure)
|
||||
*/
|
||||
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
|
||||
|
||||
private:
|
||||
|
||||
void initialize();
|
||||
};
|
||||
}
|
||||
|
||||
#endif //CONNECTOR_INTERFACE_BRIDGE_SELECTION_INFO
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "Active/Serialise/CargoHold.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Selection/GetSelection.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h"
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace connector::interfac::browser::bridge;
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Default constructor
|
||||
--------------------------------------------------------------------*/
|
||||
GetSelection::GetSelection() : BridgeMethod{"GetSelection", [&]() {
|
||||
return run();
|
||||
}} {}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get the current selection info
|
||||
based on the ArchiCAD mdoel selection
|
||||
--------------------------------------------------------------------*/
|
||||
std::unique_ptr<Cargo> GetSelection::run() const {
|
||||
auto selectionInfo = std::make_unique<SelectionInfo>();
|
||||
return std::make_unique<CargoHold<PackageWrap, SelectionInfo>>(std::move(selectionInfo));
|
||||
} //GetSelection::run
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef CONNECTOR_INTERFACE_BRIDGE_GETSELECTION
|
||||
#define CONNECTOR_INTERFACE_BRIDGE_GETSELECTION
|
||||
|
||||
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
|
||||
|
||||
namespace connector::interfac::browser::bridge {
|
||||
|
||||
class GetSelection : public speckle::interfac::browser::bridge::BridgeMethod<void, active::serialise::Cargo> {
|
||||
public:
|
||||
|
||||
// MARK: - Constructors
|
||||
|
||||
/*!
|
||||
Constructor
|
||||
@param bridge The parent bridge object (provides access to bridge methods)
|
||||
*/
|
||||
GetSelection();
|
||||
|
||||
// MARK: - Functions (const)
|
||||
|
||||
/*!
|
||||
Get the current selection info
|
||||
based on the ArchiCAD mdoel selection
|
||||
*/
|
||||
std::unique_ptr<active::serialise::Cargo> run() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //CONNECTOR_INTERFACE_BRIDGE_GETSELECTION
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "Active/Serialise/CargoHold.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Selection/SelectionBridge.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Selection/GetSelection.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Selection/Arg/SelectionInfo.h"
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace connector::interfac::browser::bridge;
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Default constructor
|
||||
--------------------------------------------------------------------*/
|
||||
SelectionBridge::SelectionBridge() : BrowserBridge{"selectionBinding"} {
|
||||
//Add bridge methods
|
||||
addMethod<GetSelection>();
|
||||
} //SelectionBridge::SelectionBridge
|
||||
|
||||
/*!
|
||||
Handle the menu selection
|
||||
@param event The selection event
|
||||
@return True if the event should be closed
|
||||
*/
|
||||
bool SelectionBridge::handle(const speckle::event::SelectionEvent& event) {
|
||||
auto selectionInfo = std::make_unique<SelectionInfo>();
|
||||
auto wrapped = std::make_unique<CargoHold<PackageWrap, SelectionInfo>>(std::move(selectionInfo));
|
||||
sendEvent("setSelection", std::move(wrapped));
|
||||
return true;
|
||||
} //SelectionBridge::handle
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef CONNECTOR_INTERFACE_BRIDGE_SELECTION_BRIDGE
|
||||
#define CONNECTOR_INTERFACE_BRIDGE_SELECTION_BRIDGE
|
||||
|
||||
#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
|
||||
#include "Speckle/Event/Subscriber/SelectionSubscriber.h"
|
||||
#include "Speckle/Event/Type/SelectionEvent.h"
|
||||
|
||||
namespace connector::interfac::browser::bridge {
|
||||
|
||||
/*!
|
||||
A browser bridge to support sending model data to a Speckle server
|
||||
*/
|
||||
class SelectionBridge : public speckle::interfac::browser::bridge::BrowserBridge, public speckle::event::SelectionSubscriber {
|
||||
public:
|
||||
|
||||
// MARK: - Types
|
||||
|
||||
using base = speckle::interfac::browser::bridge::BrowserBridge;
|
||||
|
||||
// MARK: - Constructors
|
||||
|
||||
using base::base;
|
||||
/*!
|
||||
Default constructor
|
||||
*/
|
||||
SelectionBridge();
|
||||
|
||||
protected:
|
||||
/*!
|
||||
Handle the menu selection
|
||||
@param event The selection event
|
||||
@return True if the event should be closed
|
||||
*/
|
||||
bool handle(const speckle::event::SelectionEvent& event) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //CONNECTOR_INTERFACE_BRIDGE_SELECTION_BRIDGE
|
||||
@@ -4,12 +4,14 @@
|
||||
#include "Active/Utility/String.h"
|
||||
#include "Active/Serialise/JSON/JSONTransport.h"
|
||||
#include "Active/Utility/BufferOut.h"
|
||||
#include "Connector/Connector.h"
|
||||
#include "Connector/ConnectorResource.h"
|
||||
#include "Connector/Event/ConnectorEventID.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Account/AccountBridge.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Base/BaseBridge.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Config/ConfigBridge.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Send/SendBridge.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Selection/SelectionBridge.h"
|
||||
#include "Connector/Interface/Browser/Bridge/Test/TestBridge.h"
|
||||
#include "Speckle/Environment/Addon.h"
|
||||
#include "Speckle/Event/Type/MenuEvent.h"
|
||||
@@ -76,9 +78,6 @@ namespace {
|
||||
virtual void PanelResized(const DG::PanelResizeEvent& ev) override;
|
||||
virtual void PanelCloseRequested(const DG::PanelCloseRequestEvent& ev, bool* accepted) override;
|
||||
|
||||
static GS::Array<BrowserPalette::ElementInfo> GetSelectedElements();
|
||||
static void ModifySelection(const GS::UniString& elemGuidStr, SelectionModification modification);
|
||||
|
||||
static GSErrCode __ACENV_CALL PaletteControlCallBack(Int32 paletteId, API_PaletteMessageID messageID, GS::IntPtr param);
|
||||
|
||||
static GS::Ref<BrowserPalette> instance;
|
||||
@@ -170,6 +169,12 @@ BrowserPalette::BrowserPalette() :
|
||||
install<BaseBridge>();
|
||||
install<ConfigBridge>();
|
||||
install<SendBridge>();
|
||||
if (auto ref = install<SelectionBridge>(); ref) {
|
||||
if (auto selectionBridgeRef = std::dynamic_pointer_cast<SelectionBridge>(ref); selectionBridgeRef) {
|
||||
connector::connector()->addWeak(selectionBridgeRef);
|
||||
selectionBridgeRef->start();
|
||||
}
|
||||
}
|
||||
install<TestBridge>();
|
||||
InitBrowserControl();
|
||||
}
|
||||
@@ -243,31 +248,6 @@ void BrowserPalette::PanelCloseRequested(const DG::PanelCloseRequestEvent&, bool
|
||||
*accepted = true;
|
||||
}
|
||||
|
||||
GS::Array<BrowserPalette::ElementInfo> BrowserPalette::GetSelectedElements() {
|
||||
API_SelectionInfo selectionInfo;
|
||||
GS::Array<API_Neig> selNeigs;
|
||||
ACAPI_Selection_Get(&selectionInfo, &selNeigs, false, false);
|
||||
BMKillHandle((GSHandle*)&selectionInfo.marquee.coords);
|
||||
|
||||
GS::Array<BrowserPalette::ElementInfo> selectedElements;
|
||||
for(const API_Neig& neig : selNeigs) {
|
||||
API_Elem_Head elemHead = {};
|
||||
elemHead.guid = neig.guid;
|
||||
ACAPI_Element_GetHeader(&elemHead);
|
||||
|
||||
ElementInfo elemInfo;
|
||||
elemInfo.guidStr = APIGuidToString(elemHead.guid);
|
||||
ACAPI_Element_GetElemTypeName(elemHead.type, elemInfo.typeName);
|
||||
ACAPI_Element_GetElementInfoString(&elemHead.guid, &elemInfo.elemID);
|
||||
selectedElements.Push(elemInfo);
|
||||
}
|
||||
return selectedElements;
|
||||
}
|
||||
|
||||
void BrowserPalette::ModifySelection(const GS::UniString& elemGuidStr, BrowserPalette::SelectionModification modification) {
|
||||
ACAPI_Selection_Select({ API_Neig(APIGuidFromString(elemGuidStr.ToCStr().Get())) }, modification == AddToSelection);
|
||||
}
|
||||
|
||||
GSErrCode __ACENV_CALL BrowserPalette::PaletteControlCallBack(Int32, API_PaletteMessageID messageID, GS::IntPtr param) {
|
||||
switch(messageID) {
|
||||
case APIPalMsg_OpenPalette:
|
||||
|
||||
@@ -45,17 +45,18 @@ namespace speckle::event {
|
||||
@return True if the event should be closed
|
||||
*/
|
||||
bool receive(const active::event::Event& event) override;
|
||||
|
||||
protected:
|
||||
/*!
|
||||
Start the participant operation
|
||||
@return True if the participant is able to continue
|
||||
*/
|
||||
bool start() override;
|
||||
virtual bool start() override;
|
||||
/*!
|
||||
Stop participation (release resources etc)
|
||||
*/
|
||||
void stop() override;
|
||||
|
||||
protected:
|
||||
|
||||
/*!
|
||||
Handle a selection change
|
||||
@param event The selection event
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace speckle::event {
|
||||
Constructor
|
||||
@param selected A link to a selected element (nullopt if the selection is empty)
|
||||
*/
|
||||
SelectionEvent(speckle::database::BIMLink::Option selected) : m_selectedLink{selected} {}
|
||||
SelectionEvent(speckle::database::BIMLink::Option selected) : Event{ ID }, m_selectedLink{selected} {}
|
||||
/*!
|
||||
Copy constructor
|
||||
@param source The object to copy
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace speckle::interfac::browser {
|
||||
*/
|
||||
template<class Derived>
|
||||
explicit JSObject(const speckle::utility::String& name, const std::initializer_list<Derived>& items) : base{items}, m_name{name} {}
|
||||
|
||||
virtual ~JSObject() {}
|
||||
// MARK: - Functions (const)
|
||||
|
||||
/*!
|
||||
|
||||
@@ -48,14 +48,14 @@ namespace speckle::interfac::browser {
|
||||
@param object The object to install
|
||||
@return True if the object was successfully installed
|
||||
*/
|
||||
bool install(std::shared_ptr<JSObject<FunctionBinding>> object);
|
||||
std::shared_ptr<JSObject<FunctionBinding>> install(std::shared_ptr<JSObject<FunctionBinding>> object);
|
||||
/*!
|
||||
Install a JS function object
|
||||
@return True if the object was successfully installed
|
||||
@tparam T The type of object to install
|
||||
*/
|
||||
template<typename T> requires std::is_base_of_v<JSObject<FunctionBinding>, T>
|
||||
bool install() { return install(std::make_shared<T>()); }
|
||||
std::shared_ptr<JSObject<FunctionBinding>> install() { return install(std::make_shared<T>()); }
|
||||
|
||||
protected:
|
||||
#ifdef ARCHICAD
|
||||
@@ -101,12 +101,12 @@ namespace speckle::interfac::browser {
|
||||
return: True if the object was successfully installed
|
||||
--------------------------------------------------------------------*/
|
||||
template<typename FunctionBinding>
|
||||
bool JSPortal<FunctionBinding>::install(std::shared_ptr<JSObject<FunctionBinding>> object) {
|
||||
std::shared_ptr<JSObject<FunctionBinding>> JSPortal<FunctionBinding>::install(std::shared_ptr<JSObject<FunctionBinding>> object) {
|
||||
try {
|
||||
#ifdef ARCHICAD
|
||||
auto engine = getJSEngine();
|
||||
if (!engine)
|
||||
return false;
|
||||
return nullptr;
|
||||
//Define the JS object
|
||||
JS::Object* acObject = new JS::Object(object->getName());
|
||||
//Add all the functions supported by this object
|
||||
@@ -125,13 +125,13 @@ namespace speckle::interfac::browser {
|
||||
if (engine->RegisterAsynchJSObject(acObject)) {
|
||||
base::push_back(object);
|
||||
object->setPortal(*this);
|
||||
return true;
|
||||
return object;
|
||||
}
|
||||
#endif
|
||||
} catch(...) {
|
||||
///TODO: Need to discuss the best course of action to notify of a failure
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
} //JSPortal<FunctionBinding>::install
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user