Today I fix & improve the source code of the post wxogl-vs-wxdc-vs-wxart2d that I wrote last week, and now the same application can add until 10 tables (rectangles with text) inside the frame, then you can select only one at time (red line in the border) or move it with drag & drop in the frame.
This demo can help people (newbies) who wants to create a modeling tool of some kind with WxWidgets, is not great thing but have good ideas that can be used for larger applications:
- Diagram it's draw at the OnPaint event of the windows, because this there isn't need of a separate thread or something like that. And CPU usage of application it's low.
- It's easy to adapt the example to use a Model View Controller, only create data structures with base information for objects inside diagram, and a DrawAll function that can read that information and draw it, then Controller syncrhonize all changes between the data and the image.
- Flicker have been eliminated.
- Don't use any complex third party library, this means no highly optimized rendering neither undo feature (by default) or complex document hierarchy, but for me best way of programa something always should follow this rule: "Simpler is better "
Source code:
Test.cpp
- #include "wx/wxprec.h"
- #define MAXRECTANGLES 10
- #ifdef __BORLANDC__
- #pragma hdrstop
- #endif
- #ifndef WX_PRECOMP
- #endif
- #include "wx/wx.h"
- #include "wx/dcbuffer.h"
- enum MenuItems
- {
- ID_Add = 2,
- ID_Quit = 1,
- ID_About = 0,
- };
- class MyApp: public wxApp
- {
- virtual bool OnInit();
- };
- IMPLEMENT_APP(MyApp)
- class MyCanvas; //Just a prototype
- class MyFrame: public wxFrame
- {
- public:
- MyFrame(const wxString& title,
- const wxPoint& pos, const wxSize& size);
- //Menu Events
- void OnQuit(wxCommandEvent& event);
- void OnAbout(wxCommandEvent& event);
- void OnAddRectangle(wxCommandEvent& event);
- //Global Class Variables
- MyCanvas *paintArea;
- DECLARE_EVENT_TABLE()
- };
- class MyCanvas: public wxScrolledWindow
- {
- public:
- MyCanvas::MyCanvas(MyFrame *parent, wxSize size);
- //MyCanvas Functions
- void MyCanvas::DrawAll(wxBufferedDC& bdc);
- int MyCanvas::GetIndexSelected();
- //MyCanvas Events
- void MyCanvas::OnPaint(wxPaintEvent& event);
- void MyCanvas::OnMotion(wxMouseEvent& event);
- void MyCanvas::OnErase(wxEraseEvent& event);
- void MyCanvas::OnEraseBackGround(wxEraseEvent& event);
- //Global Class Variables
- int rts[MAXRECTANGLES][2];
- int rts_Size;
- int pressed,posx,posy,selected;
- wxSize c_size;
- private:
- MyFrame *m_owner;
- DECLARE_EVENT_TABLE()
- };
- //**********************Begin implementations
- bool MyApp::OnInit()
- {
- MyFrame *frame = new MyFrame( wxT("Hello World Drawing in 2D"),
- wxPoint(50,50), wxSize(800,600) );
- frame->Show(TRUE);
- SetTopWindow(frame);
- //frame->SetScrollbar(wxVERTICAL,0,16,50);
- //initialize values
- frame->paintArea->rts_Size=0;
- for(int i=0;i<MAXRECTANGLES;i++){
- frame->paintArea->rts[i][0]=-1;
- frame->paintArea->rts[i][1]=-1;
- }
- frame->paintArea->pressed=-1; //No rectangle selected
- return TRUE;
- }
- //MyFrame Constructor
- MyFrame::MyFrame(const wxString& title,
- const wxPoint& pos, const wxSize& size)
- : wxFrame((wxFrame *)NULL, -1, title, pos, size)
- {
- wxMenu *menuFile = new wxMenu;
- menuFile->Append( ID_Add, wxT("&Add new Rectangle..." ));
- menuFile->Append( ID_About, wxT("A&bout..." ));
- menuFile->AppendSeparator();
- menuFile->Append( ID_Quit, wxT("E&xit" ));
- wxMenuBar *menuBar = new wxMenuBar;
- menuBar->Append( menuFile, wxT("&File") );
- SetMenuBar( menuBar );
- CreateStatusBar();
- SetStatusText(wxT("Proof of Concept drawing") );
- paintArea = new MyCanvas(this,wxSize(800,600));
- paintArea->SetScrollbars( 10, 10, 100, 240 );
- }
- //MyCanvas Constructor
- MyCanvas::MyCanvas(MyFrame *parent, wxSize size)
- : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, size,
- wxHSCROLL | wxVSCROLL | wxBORDER | wxRETAINED)
- {
- m_owner = parent;
- c_size = size;
- }
- //Events Table Macros
- BEGIN_EVENT_TABLE(MyFrame, wxFrame)
- EVT_MENU(ID_Quit, MyFrame::OnQuit)
- EVT_MENU(ID_About, MyFrame::OnAbout)
- EVT_MENU(ID_Add, MyFrame::OnAddRectangle)
- END_EVENT_TABLE()
- BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
- EVT_PAINT(MyCanvas::OnPaint)
- EVT_MOTION(MyCanvas::OnMotion)
- EVT_LEFT_DOWN(MyCanvas::OnMotion)
- EVT_LEFT_UP(MyCanvas::OnMotion)
- EVT_ERASE_BACKGROUND(MyCanvas::OnEraseBackGround)
//This erase flicker create by wxStaticText when erasing background but this is not needed - END_EVENT_TABLE()
- //Events **************************
- //Overwrite and disable onEraseBackground Event to avoid Flicker
- void MyCanvas::OnEraseBackGround(wxEraseEvent& event) {};
- void MyCanvas::OnPaint(wxPaintEvent& event)
- {
- //Prepare Context for Buffered Draw
- wxPaintDC dcc(this);
- wxBufferedDC dc(&dcc, c_size );
- DrawAll(dc);
- }
- void MyCanvas::OnMotion(wxMouseEvent& event)
- {
- posx=event.GetPosition().x;
- posy=event.GetPosition().y;
- this->CalcUnscrolledPosition(posx,posy,&posx,&posy);
- if(event.ButtonDown()&&pressed==-1){
- pressed=GetIndexSelected();
- selected=pressed;
- }
- if(event.ButtonUp()){
- pressed=-1;
- }
- if (event.Dragging()&&pressed!=-1)
- {
- rts[pressed][0]=posx-25;
- rts[pressed][1]=posy-25;
- }
- this->Refresh();
- }
- //**************************Functions
- int MyCanvas::GetIndexSelected(){
- int index=-1;
- for(int i=0;i<rts_Size;i++){
- int x=rts[i][0];
- int y=rts[i][1];
- if( ((posx-x>0)&&(x+70>posx)) && ((posy-y>0)&&(y+70>posy)) ){
- return i;
- break;
- }
- }
- return index;
- }
- void MyCanvas::DrawAll(wxBufferedDC& bdc){
- bdc.SetBackground(*wxBLACK_BRUSH);
- wxFont f = wxFont(8, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
- wxFont f2 = wxFont(10, wxFONTFAMILY_ROMAN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
- bdc.Clear();
- bdc.SetBrush(*wxWHITE_BRUSH);
- for(int i=(rts_Size-1);i>=0;i--){ //i-- to draw in order
- int x=rts[i][0];
- int y=rts[i][1];
- this->CalcScrolledPosition(x,y,&x,&y);
- if(x!=-1 && y!=-1){
- if(selected==i){
- bdc.SetPen(*wxRED_PEN);
- }else{
- bdc.SetPen(*wxBLACK_PEN);
- }
- bdc.DrawRectangle(wxRect(wxPoint(x,y), wxSize(70,70)));
- bdc.SetFont(f2);
- bdc.DrawText(wxT("TName"),x+5,y);
- bdc.SetFont(f);
- bdc.DrawText(wxT("CName 1"),x+10,y+12); //use font metrics here
- bdc.DrawText(wxT("CName 2"),x+10,y+24); //use font metrics here
- bdc.DrawText(wxT("CName 3"),x+10,y+36); //use font metrics here
- bdc.DrawText(wxT("CName ..."),x+10,y+36); //use font metrics here
- }
- else{
- break;
- }
- }
- }
- //**************************Menu Events
- void MyFrame::OnAddRectangle(wxCommandEvent& WXUNUSED(event))
- {
- if(paintArea->rts_Size < MAXRECTANGLES){
- paintArea->rts[paintArea->rts_Size][0]= paintArea->rts_Size*10+10;
- paintArea->rts[paintArea->rts_Size][1]= paintArea->rts_Size*10+10;
- paintArea->rts_Size++;
- }
- }
- void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
- { Close(TRUE);
- }
- void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
- { wxMessageBox(wxT("This is a Hello Direct Contex Application in wxWidgets"),
- wxT("About Hello DC"), wxOK | wxICON_INFORMATION, this);
- }
No hay comentarios:
Publicar un comentario