Tesseract  3.02
tesseract-ocr/viewer/svpaint.cpp
Go to the documentation of this file.
00001 // Copyright 2007 Google Inc. All Rights Reserved.
00002 //
00003 // Author: Joern Wanke
00004 //
00005 // Simple drawing program to illustrate ScrollView capabilities.
00006 //
00007 // Functionality:
00008 // - The menubar is used to select from different sample styles of input.
00009 // - With the RMB it is possible to change the RGB values in different
00010 //   popup menus.
00011 // - A LMB click either draws point-to-point, point or text.
00012 // - A LMB dragging either draws a line, a rectangle or ellipse.
00013 
00014 #include "scrollview.h"
00015 #include "svmnode.h"
00016 #include <stdlib.h>
00017 #include <iostream>
00018 
00019 #ifndef GRAPHICS_DISABLED
00020 // The current color values we use, initially white (== ScrollView::WHITE).
00021 int rgb[3] = { 255, 255, 255 };
00022 
00023 class SVPaint : public SVEventHandler {
00024  public:
00025    SVPaint(const char* server_name);
00026 // This is the main event handling function that we need to overwrite, defined
00027 // in SVEventHandler.
00028    void Notify(const SVEvent* sv_event);
00029  private:
00030 // The Handler take care of the SVET_POPUP, SVET_MENU, SVET_CLICK and
00031 // SVET_SELECTION events.
00032    void PopupHandler(const SVEvent* sv_event);
00033    void MenuBarHandler(const SVEvent* sv_event);
00034    void ClickHandler(const SVEvent* sv_event);
00035    void SelectionHandler(const SVEvent* sv_event);
00036 
00037 // Convenience functions to build little menus.
00038    SVMenuNode* BuildPopupMenu();
00039    SVMenuNode* BuildMenuBar();
00040 
00041 // Our window.
00042    ScrollView* window_;
00043 
00044 // The mode we are in when an SVET_CLICK or an SVET_SELECTION event occurs.
00045    int click_mode_;
00046    int drag_mode_;
00047 
00048 // In the point-to-point drawing mode, we need to set a start-point the first
00049 // time we call it (e.g. call SetCursor).
00050    bool has_start_point_;
00051 };
00052 
00053 // Build a sample popup menu.
00054 SVMenuNode* SVPaint::BuildPopupMenu() {
00055   SVMenuNode* root = new SVMenuNode();  // Empty root node
00056   // Initial color is white, so we  all values to 255.
00057   root->AddChild("R",                   // Shown caption.
00058                   1,                    // assoc. command_id.
00059                  "255",                 // initial value.
00060                  "Red Color Value?");  // Shown description.
00061   root->AddChild("G", 2, "255", "Green Color Value?");
00062   root->AddChild("B", 3, "255", "Blue Color Value?");
00063   return root;
00064 }
00065 
00066 // Build a sample menu bar.
00067 SVMenuNode* SVPaint::BuildMenuBar() {
00068   SVMenuNode* root = new SVMenuNode();  // Empty root node
00069 
00070   // Create some submenus and add them to the root.
00071   SVMenuNode* click = root->AddChild("Clicking");
00072   SVMenuNode* drag = root->AddChild("Dragging");
00073   
00074   // Put some nodes into the submenus.
00075   click->AddChild("Point to Point Drawing",  // Caption.
00076                   1);                       // command_id.
00077   click->AddChild("Point Drawing", 2);
00078   click->AddChild("Text Drawing", 3);
00079   drag->AddChild("Line Drawing", 4);
00080   drag->AddChild("Rectangle Drawing", 5);
00081   drag->AddChild("Ellipse Drawing", 6);
00082   return root;
00083 }
00084 
00085 // Takes care of the SVET_POPUP events.
00086 // In our case, SVET_POPUP is used to set RGB values.
00087 void SVPaint::PopupHandler(const SVEvent* sv_event) {
00088   // Since we only have the RGB values as popup items,
00089   // we take a shortcut to not bloat up code:
00090   rgb[sv_event->command_id - 1] = atoi(sv_event->parameter);
00091   window_->Pen(rgb[0], rgb[1], rgb[2]);
00092 }
00093 
00094 // Takes care of the SVET_MENU events.
00095 // In our case, we change either the click_mode_ (commands 1-3)
00096 // or the drag_mode_ (commands 4-6).
00097 void SVPaint::MenuBarHandler(const SVEvent* sv_event) {
00098   if ((sv_event->command_id > 0) && (sv_event->command_id < 4)) { 
00099   click_mode_ = sv_event->command_id;   
00100   has_start_point_ = false;
00101   } else { drag_mode_ = sv_event->command_id; }
00102 }
00103 
00104 // Takes care of the SVET_CLICK events.
00105 // Depending on the click_mode_ we are in, either do Point-to-Point drawing,
00106 // point drawing, or draw text.
00107 void SVPaint::ClickHandler(const SVEvent* sv_event) {
00108   switch (click_mode_) {
00109   case 1: //Point to Point
00110     if (has_start_point_) { window_->DrawTo(sv_event->x, sv_event->y);
00111     } else {
00112         has_start_point_ = true; 
00113         window_->SetCursor(sv_event->x, sv_event->y);
00114     }
00115     break;
00116   case 2: //Point Drawing..simulated by drawing a 1 pixel line.
00117     window_->Line(sv_event->x, sv_event->y, sv_event->x, sv_event->y);
00118     break;
00119   case 3: //Text
00120     // We show a modal input dialog on our window, then draw the input and
00121     // finally delete the input pointer.
00122     char* p = window_->ShowInputDialog("Text:");
00123     window_->Text(sv_event->x, sv_event->y, p);
00124     delete p;
00125     break;
00126   }
00127 }
00128 
00129 // Takes care of the SVET_SELECTION events.
00130 // Depending on the drag_mode_ we are in, either draw a line, a rectangle or
00131 // an ellipse.
00132 void SVPaint::SelectionHandler(const SVEvent* sv_event) {
00133   switch (drag_mode_) {
00134   //FIXME inversed x_size, y_size
00135     case 4: //Line
00136       window_->Line(sv_event->x, sv_event->y, 
00137                     sv_event->x - sv_event->x_size,
00138                     sv_event->y - sv_event->y_size);
00139       break;
00140     case 5: //Rectangle
00141       window_->Rectangle(sv_event->x, sv_event->y,
00142                          sv_event->x - sv_event->x_size,
00143                          sv_event->y - sv_event->y_size);
00144       break;
00145     case 6: //Ellipse
00146       window_->Ellipse(sv_event->x - sv_event->x_size,
00147                        sv_event->y - sv_event->y_size,
00148                        sv_event->x_size, sv_event->y_size);
00149       break;
00150     }
00151 }
00152 
00153 // The event handling function from ScrollView which we have to overwrite.
00154 // We handle CLICK, SELECTION, MENU and POPUP and throw away all other events.
00155 void SVPaint::Notify(const SVEvent* sv_event) {
00156   if (sv_event->type == SVET_CLICK) { ClickHandler(sv_event); }  
00157   else if (sv_event->type == SVET_SELECTION) { SelectionHandler(sv_event); }
00158   else if (sv_event->type == SVET_MENU) { MenuBarHandler(sv_event); }
00159   else if (sv_event->type == SVET_POPUP) { PopupHandler(sv_event); }
00160   else {} //throw other events away
00161 }
00162 
00163 // Builds a new window, initializes the variables and event handler and builds
00164 // the menu.
00165 SVPaint::SVPaint(const char *server_name) {
00166   window_ = new ScrollView("ScrollView Paint Example",  // window caption
00167                             0, 0,                       // x,y window position
00168                             500, 500,                   // window size
00169                                     500, 500,                   // canvas size
00170                             false,      // whether the Y axis is inversed.
00171                                         // this is included due to legacy 
00172                                         // reasons for tesseract and enables
00173                                         // us to have (0,0) as the LOWER left
00174                                         // of the coordinate system.
00175                             server_name);               // the server address.
00176 
00177   // Set the start modes to point-to-point and line drawing.
00178   click_mode_ = 1;
00179   drag_mode_ = 4;
00180   has_start_point_ = false;
00181 
00182   // Bild our menus and add them to the window. The flag illustrates whether
00183   // this is a menu bar.
00184   SVMenuNode* popup_menu = BuildPopupMenu();
00185   popup_menu->BuildMenu(window_,false);
00186         
00187   SVMenuNode* bar_menu = BuildMenuBar();
00188   bar_menu->BuildMenu(window_,true);
00189 
00190   // Set the initial color values to White (could also be done by
00191   // passing (rgb[0], rgb[1], rgb[2]).
00192   window_->Pen(ScrollView::WHITE);
00193   window_->Brush(ScrollView::WHITE);
00194 
00195   // Adds the event handler to the window. This actually ensures that Notify
00196   // gets called when events occur.
00197   window_->AddEventHandler(this);
00198 
00199   // Set the window visible (calling this is important to actually render
00200   // everything. Without this call, the window would also be drawn, but the
00201   // menu bars would be missing.
00202   window_->SetVisible(true);
00203 
00204   // Rest this thread until its window is destroyed.
00205   // Note that a special eventhandling thread was created when constructing
00206   // the window. Due to this, the application will not deadlock here.
00207   window_->AwaitEvent(SVET_DESTROY);
00208   // We now have 3 Threads running:
00209   // (1) The MessageReceiver thread which fetches messages and distributes them
00210   // (2) The EventHandler thread which handles all events for window_
00211   // (3) The main thread which waits on window_ for a DESTROY event (blocked)
00212 }
00213 
00214 // If a parameter is given, we try to connect to the given server.
00215 // This enables us to test the remote capabilites of ScrollView.
00216 int main(int argc, char** argv) {
00217         const char* server_name;
00218         if (argc > 1) { server_name = argv[1]; } else { server_name = "localhost"; }
00219         SVPaint svp(server_name);
00220 }
00221 #endif  // GRAPHICS_DISABLED