XT框架中界面布局的定制通过继承UIProxy实现。
应用界面依赖于应用文档,因此应用界面的注册是通过调用XDocument提供的静态函数完成:
static bool bRegisterTestUI = LOCAL_NAMESPACE::XDocument::registerUIProxy(DocumentTestID, CreateTestProxy, DestroyTestProxy);
其中DocumentTestID是注册应用文档时生成的整型ID标识,后面的两个参数分别为Proxy的构造接口和析构接口,在接口中调用具体的构造函数与析构函数(所有的界面代理均需重新实现这两个接口):
bool CreateTestProxy(MainFrame* frame, XDocument * doc,UIProxy ** proxy)
{
TestProxy * t = new TestProxy(frame,doc);
if (t == 0)
{
return false;
}
*proxy = t;
return true;
}
void DestroyTestProxy(UIProxy * proxy)
{
delete static_cast<TestProxy *>(proxy);
}
在界面代理的构造函数,根据应用的需要添加视图、定制窗口布局和创建对象树模型,其中对象树模型根据Qt库中QTreeView控件的MVC设计思路而来,用于向XTreeView提供数据(XTreeView从QTreeView继承实现,可参看相关文档):
TestProxy::TestProxy(MainFrame * frame,XDocument * doc):UIProxy(frame,doc)
{
//创建对象树Model,按照QTreeView控件的MVC机制
m_pDocTreeMdl = new TestTreeModel(m_pDoc, m_pFrame);
//添加新的视图
m_pCurrentDocView = new TestView(m_pFrame, m_pDoc);
m_pDocViews->push_back(m_pCurrentDocView);
//定制窗口
m_pCmdDock = new QDockWidget(QString().fromLocal8Bit("设置"), m_pFrame);
m_pCmdDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
m_pCmdDock->setAllowedAreas(Qt::AllDockWidgetAreas);
}
在启动与应用文档适配的应用界面之前,应重新实现activate函数以正确的激活对应的界面代理,在此函数中主要对界面窗口重新布局,设置该应用界面特有的属性,如程序名称、三维视图背景色等等,并恢复之前的界面状态(在多个应用来回切换的情况下), 如视图视角等等:
void TestProxy::activate()
{
UIProxy::activate();
//设置功能对话框样式
auto cmdWnd = static_cast<XCommandWnd*>(m_pFrame->getCommandWindow());
cmdWnd->setStyleSheet(QString("background-color:#F8F8F8; "));
//设置程序名称
m_pFrame->setWindowTitle(QString().fromLocal8Bit("静力分析前处理"));
//恢复视图视角
if (m_pDoc->getViewData()->getVisualAngle()->isValid())getRender()->loadVisualAngle(m_pDoc->getViewData()->getVisualAngle());
//设置视图背景色
XPreference::getInstance()->setVariable(_RENDER_BACKGROUND_TOP_COLOR, "216,216,255", "ui");
XPreference::getInstance()->setVariable(_RENDER_BACKGROUND_BOTTOM_COLOR, "128,128,192", "ui");
getRender()->updateColorSetting();
getRender()->refresh();
//布局子窗口
auto treeDock = m_pFrame->getDock(m_pFrame->getObjectTree());
m_pFrame->removeDockWidget(treeDock);
m_pFrame->addDockWidget(Qt::LeftDockWidgetArea, treeDock);
auto prpDock = m_pFrame->getDock(m_pFrame->getPropertyWnd());
m_pFrame->removeDockWidget(prpDock);
m_pFrame->addDockWidget(Qt::LeftDockWidgetArea, prpDock);
auto pickDock = m_pFrame->getDock(m_pFrame->getPickWnd());
m_pFrame->removeDockWidget(pickDock);
m_pFrame->addDockWidget(Qt::LeftDockWidgetArea, pickDock);
auto msgDock = m_pFrame->getDock(m_pFrame->getMessageWnd());
m_pFrame->removeDockWidget(msgDock);
m_pFrame->addDockWidget(Qt::BottomDockWidgetArea, msgDock);
m_pFrame->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
m_pCmdDock->setWidget(cmdWnd);
cmdWnd->setWndButtonVisible(Wnd_OK | Wnd_Cancel, false);
m_pFrame->addDockWidget(Qt::LeftDockWidgetArea, m_pCmdDock);
treeDock->showNormal();
msgDock->showNormal();
prpDock->showNormal();
pickDock->showNormal();
m_pCmdDock->showNormal();
m_pFrame->splitDockWidget(treeDock, m_pCmdDock, Qt::Horizontal);
m_pFrame->splitDockWidget(treeDock, prpDock, Qt::Vertical);
pickDock->hide();
}
在离开该应用界面时,也应重新实现deactivate函数以清除该应用特有的设定,如固定功能对话框变为浮动对话框等等。
void PreUIProxy::deactivate()
{
auto cmdWnd = static_cast<XCommandWnd*>(m_pFrame->getCommandWindow());
cmdWnd->setDockFixed(false);
getRender()->saveVisualAngle(m_pDoc->getViewData()->getVisualAngle());
UIProxy::deactivate();
m_pFrame->removeDockWidget(m_pCmdDock);
cmdWnd->setParent(m_pFrame);
m_pCmdDock->setWidget(0);
m_pCmdDock->hide();
}
一般的,当用户在对象树上单击某个对象时会在XPropertyWnd显示其属性,如果希望在XPropertyWnd显示一些特殊的属性时,界面代理需要重新实现listProperty接口,如果希望显示材料分配的数量,按如下代码实现即可:
void TestProxy::listProperty(TypeID type,const XItem * item,TypeID domainType )
{
const XItem * di = (const XItem *)item;
auto doc = m_pFrame->getCurrentDocument();
XPropertyWnd * psw = m_pFrame->getPropertyWnd();
if (type == Domain_Material) {
psw->clear();
psw->addItem(&SheetItem("材料数量", doc->getItemManager(Domain_Material)->getItemCount()));
psw->addItem(&SheetItem("材料分配数量", doc->getItemManager(Domain_Property)->getItemCount()));
}
else
return UIProxy::listProperty(type, item, domainType);
}