Introduction
Free for PERSONAL and COMMERCIAL use
The SolidWidgets UI framework includes a very powerful dialog editor component that can be embedded directly in application.
If you ever had a requirement to build an interactive visual designer that the users can use to design screen layouts, move around dialog resources, etc, you
already know how difficult it is to build such functionality. This Visual Editor component included in the SolidWidgets library gives you the solution
to this problem. The component is extremely simple to use, and can easily be integrated with any SolidWidgets application. I have been truly impressed with how much
functionality this library includes, and the great design of the overall framework. Following is a short tutorial to quickly show how this component is used.
Using the Dialog Editor component
Following are the steps needed to integrate this component into your application:
- Create a dialog or a frame class, and make the class inherit
swVisualEditorListener
.
swVisualEditorListener
requires you to implement two functions that give you control over the types of objects that the user adds or modify at runtime. - Include the header swVisualEditor.h:
#include <swVisualEditor.h>
- Implement the following functions in your class:
public: void paint(swGDI *g,const swString& objId,const swString& objText,
long x,long y,long width,long height);
BOOL editObjectProperties(swString& objId,swString& objText);
- Add your code in the paint function to implement custom painting of the objects.
- Add your code in
editObjectProperties
to allow the user to edit the properties of the object.
The visual designer component tracks the id, text, and position of each object, you can maintain a separate list that tracks whatever other information your application requires about each object.
The best way to do this is to have a list of object records, where each record has a matching id to an object in the component, and the record will have other attributes
that describe the object. For example,
class VEditDialog: public swDialog, public swVisualEditorListener
{
class ScreenObject
{
public:
swString objId;
long objectType; swString pictureFilePath;
};
swVector<ScreenObject> m_screenObjects;
swVisualEditor m_designer;
swButton m_okBtn,m_cancelBtn;
public:
void windowOpening();
void windowOpened();
BOOL windowClosing();
void windowClosed();
void actionPerformed(long sourceId,long eventId,const swString& eventName);
public:
void paint(swGDI *g,const swString& objId,const swString& objText,long x,long y,long width,long height);
BOOL editObjectProperties(swString& objId,swString& objText);
};
Sample implementation of the paint method:
void paint(swGDI *g,const swString& objId,const swString& objText,long x,long y,long width,long height)
{
long matchingObjectIndex = -1;
long numObjects = m_screenObjects.size();
for(long i=0;i<numObjects;i++)
{
if(m_screenObjects[i].objId.equalsIgnoreCase(objId))
{
matchingObjectIndex = i;
break;
}
}
Rect objRect;
objRect.SetRect(x,y,x+width-1,y+height-1);
g->fillRect(objRect,swColor(255,255,255));
if(matchingObjectIndex>=0)
{
if(m_screenObjects[i].objectType == LABEL)
g->drawString(objText,objRect,ALIGNMENT_CENTER);
else if(m_screenObjects[i].objectType == TEXTFIELD)
{
g->drawString(objText,objRect,ALIGNMENT_CENTER);
g->draw3DRect(objRect,FALSE);
}
else if(m_screenObjects[i].objectType == PICTURE)
{
g->drawImageFile(m_screenObjects[i].pictureFilePath,objRect,FALSE);
g->drawRect(objRect);
}
}
}
Sample implementation of the editObjectProperties method:
BOOL editObjectProperties(swString& objId,swString& objText)
{
long matchingObjectIndex = -1;
long numObjects = m_screenObjects.size();
for(long i=0;i<numObjects;i++)
{
if(m_screenObjects[i].objId.equalsIgnoreCase(objId))
{
matchingObjectIndex = i;
break;
}
}
if(matchingObjectIndex>=0) {
}
else {
ScreenObject newObj;
newObj.objId = swString::static_fromLong(m_designer.getObjectCount()+1);
m_screenObjects.push_back(newObj);
matchingObjectIndex = m_screenObjects.size()-1; objId = newObj.objId; }
if(matchingObjectIndex>=0)
{
return TRUE;
}
return FALSE;
}
Here is the resulting code:
#include <swDialog.h>
#include <swVisualEditor.h>
#include <swButton.h>
class VEditDialog: public swDialog, public swVisualEditorListener
{
class ScreenObject
{
public:
swString objId;
long objectType; swString pictureFilePath;
};
swVector<ScreenObject> m_screenObjects;
swVisualEditor m_designer;
swButton m_okBtn,m_cancelBtn;
public:
void windowOpening();
void windowOpened();
BOOL windowClosing();
void windowClosed();
void actionPerformed(long sourceId,long eventId,const swString& eventName);
public:
void paint(swGDI *g,const swString& objId,const swString& objText,
long x,long y,long width,long height);
BOOL editObjectProperties(swString& objId,swString& objText);
};
#include "VEditDialog.h"
void VEditDialog::windowOpening()
{
setSize(800,600);
swPanel *contentPane = getContentPane();
if(contentPane!=NULL)
{
contentPane->setMargins(10,10,10,10);
contentPane->addRow();
contentPane->addRow(10);
contentPane->addRow(25);
contentPane->addColumn();
contentPane->addColumn(100); contentPane->addColumn(100);
contentPane->addChild(&m_designer,0,0,3,1); contentPane->addChild(&m_okBtn,1,2,1,1); contentPane->addChild(&m_cancelBtn,2,2,1,1); }
m_designer.setListener(this);
m_okBtn.setActionListener(this);
m_okBtn.setText(L"OK");
m_cancelBtn.setActionListener(this);
m_cancelBtn.setText(L"Cancel");
}
void VEditDialog::windowOpened()
{
}
BOOL VEditDialog::windowClosing()
{
return TRUE;
}
void VEditDialog::windowClosed()
{
}
void VEditDialog::actionPerformed(long sourceId,long eventId,const swString& eventName)
{
if(sourceId == m_okBtn.getID())
{
dispose(swOK);
}
else if(sourceId == m_cancelBtn.getID())
{
dispose(swCANCEL);
}
}
void VEditDialog::paint(swGDI *g,const swString& objId,
const swString& objText,long x,long y,long width,long height)
{
long matchingObjectIndex = -1;
long numObjects = m_screenObjects.size();
for(long i=0;i<numObjects;i++)
{
if(m_screenObjects[i].objId.equalsIgnoreCase(objId))
{
matchingObjectIndex = i;
break;
}
}
Rect objRect;
objRect.SetRect(x,y,x+width-1,y+height-1);
g->fillRect(objRect,swColor(255,255,255));
if(matchingObjectIndex>=0)
{
if(m_screenObjects[i].objectType == LABEL)
g->drawString(objText,objRect,ALIGNMENT_CENTER);
else if(m_screenObjects[i].objectType == TEXTFIELD)
{
g->drawString(objText,objRect,ALIGNMENT_CENTER);
g->draw3DRect(objRect,FALSE);
}
else if(m_screenObjects[i].objectType == PICTURE)
{
g->drawImageFile(m_screenObjects[i].pictureFilePath,objRect,FALSE);
g->drawRect(objRect);
}
}
}
BOOL VEditDialog::editObjectProperties(swString& objId,swString& objText)
{
long matchingObjectIndex = -1;
long numObjects = m_screenObjects.size();
for(long i=0;i<numObjects;i++)
{
if(m_screenObjects[i].objId.equalsIgnoreCase(objId))
{
matchingObjectIndex = i;
break;
}
}
if(matchingObjectIndex>=0) {
}
else {
ScreenObject newObj;
newObj.objId = swString::static_fromLong(m_designer.getObjectCount()+1);
m_screenObjects.push_back(newObj);
matchingObjectIndex = m_screenObjects.size()-1; objId = newObj.objId; }
if(matchingObjectIndex>=0)
{
return TRUE;
}
return FALSE;
}
Final outcome:
Points of interest
As easy and simplistic as this code looks, you will start realizing the power of this framework as you dig deeper into the various components.
You can find more help on http://www.solidwidgets.com. The site includes a bunch of examples on how to use each component.
Conclusion
I hope this tutorial helps someone who needs to implement such functionality. Best of luck!