-
Notifications
You must be signed in to change notification settings - Fork 9.6k
/
svpaint.cpp
235 lines (209 loc) · 8.9 KB
/
svpaint.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
// Copyright 2007 Google Inc. All Rights Reserved.
//
// Author: Joern Wanke
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Simple drawing program to illustrate ScrollView capabilities.
//
// Functionality:
// - The menubar is used to select from different sample styles of input.
// - With the RMB it is possible to change the RGB values in different
// popup menus.
// - A LMB click either draws point-to-point, point or text.
// - A LMB dragging either draws a line, a rectangle or ellipse.
// Include automatically generated configuration file if running autoconf.
#ifdef HAVE_CONFIG_H
#include "config_auto.h"
#endif
#ifndef GRAPHICS_DISABLED
#include "scrollview.h"
#include "svmnode.h"
#include <cstdlib>
#include <iostream>
// The current color values we use, initially white (== ScrollView::WHITE).
static int rgb[3] = { 255, 255, 255 };
class SVPaint : public SVEventHandler {
public:
explicit SVPaint(const char* server_name);
// This is the main event handling function that we need to overwrite, defined
// in SVEventHandler.
void Notify(const SVEvent* sv_event) override;
private:
// The Handler take care of the SVET_POPUP, SVET_MENU, SVET_CLICK and
// SVET_SELECTION events.
void PopupHandler(const SVEvent* sv_event);
void MenuBarHandler(const SVEvent* sv_event);
void ClickHandler(const SVEvent* sv_event);
void SelectionHandler(const SVEvent* sv_event);
// Convenience functions to build little menus.
SVMenuNode* BuildPopupMenu();
SVMenuNode* BuildMenuBar();
// Our window.
ScrollView* window_;
// The mode we are in when an SVET_CLICK or an SVET_SELECTION event occurs.
int click_mode_;
int drag_mode_;
// In the point-to-point drawing mode, we need to set a start-point the first
// time we call it (e.g. call SetCursor).
bool has_start_point_;
};
// Build a sample popup menu.
SVMenuNode* SVPaint::BuildPopupMenu() {
auto* root = new SVMenuNode(); // Empty root node
// Initial color is white, so we all values to 255.
root->AddChild("R", // Shown caption.
1, // assoc. command_id.
"255", // initial value.
"Red Color Value?"); // Shown description.
root->AddChild("G", 2, "255", "Green Color Value?");
root->AddChild("B", 3, "255", "Blue Color Value?");
return root;
}
// Build a sample menu bar.
SVMenuNode* SVPaint::BuildMenuBar() {
auto* root = new SVMenuNode(); // Empty root node
// Create some submenus and add them to the root.
SVMenuNode* click = root->AddChild("Clicking");
SVMenuNode* drag = root->AddChild("Dragging");
// Put some nodes into the submenus.
click->AddChild("Point to Point Drawing", // Caption.
1); // command_id.
click->AddChild("Point Drawing", 2);
click->AddChild("Text Drawing", 3);
drag->AddChild("Line Drawing", 4);
drag->AddChild("Rectangle Drawing", 5);
drag->AddChild("Ellipse Drawing", 6);
return root;
}
// Takes care of the SVET_POPUP events.
// In our case, SVET_POPUP is used to set RGB values.
void SVPaint::PopupHandler(const SVEvent* sv_event) {
// Since we only have the RGB values as popup items,
// we take a shortcut to not bloat up code:
rgb[sv_event->command_id - 1] = atoi(sv_event->parameter);
window_->Pen(rgb[0], rgb[1], rgb[2]);
}
// Takes care of the SVET_MENU events.
// In our case, we change either the click_mode_ (commands 1-3)
// or the drag_mode_ (commands 4-6).
void SVPaint::MenuBarHandler(const SVEvent* sv_event) {
if ((sv_event->command_id > 0) && (sv_event->command_id < 4)) {
click_mode_ = sv_event->command_id;
has_start_point_ = false;
} else { drag_mode_ = sv_event->command_id; }
}
// Takes care of the SVET_CLICK events.
// Depending on the click_mode_ we are in, either do Point-to-Point drawing,
// point drawing, or draw text.
void SVPaint::ClickHandler(const SVEvent* sv_event) {
switch (click_mode_) {
case 1: //Point to Point
if (has_start_point_) { window_->DrawTo(sv_event->x, sv_event->y);
} else {
has_start_point_ = true;
window_->SetCursor(sv_event->x, sv_event->y);
}
break;
case 2: //Point Drawing..simulated by drawing a 1 pixel line.
window_->Line(sv_event->x, sv_event->y, sv_event->x, sv_event->y);
break;
case 3: //Text
// We show a modal input dialog on our window, then draw the input and
// finally delete the input pointer.
char* p = window_->ShowInputDialog("Text:");
window_->Text(sv_event->x, sv_event->y, p);
delete [] p;
break;
}
}
// Takes care of the SVET_SELECTION events.
// Depending on the drag_mode_ we are in, either draw a line, a rectangle or
// an ellipse.
void SVPaint::SelectionHandler(const SVEvent* sv_event) {
switch (drag_mode_) {
//FIXME inversed x_size, y_size
case 4: //Line
window_->Line(sv_event->x, sv_event->y,
sv_event->x - sv_event->x_size,
sv_event->y - sv_event->y_size);
break;
case 5: //Rectangle
window_->Rectangle(sv_event->x, sv_event->y,
sv_event->x - sv_event->x_size,
sv_event->y - sv_event->y_size);
break;
case 6: //Ellipse
window_->Ellipse(sv_event->x - sv_event->x_size,
sv_event->y - sv_event->y_size,
sv_event->x_size, sv_event->y_size);
break;
}
}
// The event handling function from ScrollView which we have to overwrite.
// We handle CLICK, SELECTION, MENU and POPUP and throw away all other events.
void SVPaint::Notify(const SVEvent* sv_event) {
if (sv_event->type == SVET_CLICK) { ClickHandler(sv_event); }
else if (sv_event->type == SVET_SELECTION) { SelectionHandler(sv_event); }
else if (sv_event->type == SVET_MENU) { MenuBarHandler(sv_event); }
else if (sv_event->type == SVET_POPUP) { PopupHandler(sv_event); }
//throw other events away
}
// Builds a new window, initializes the variables and event handler and builds
// the menu.
SVPaint::SVPaint(const char *server_name) {
window_ = new ScrollView("ScrollView Paint Example", // window caption
0, 0, // x,y window position
500, 500, // window size
500, 500, // canvas size
false, // whether the Y axis is inversed.
// this is included due to legacy
// reasons for tesseract and enables
// us to have (0,0) as the LOWER left
// of the coordinate system.
server_name); // the server address.
// Set the start modes to point-to-point and line drawing.
click_mode_ = 1;
drag_mode_ = 4;
has_start_point_ = false;
// Bild our menus and add them to the window. The flag illustrates whether
// this is a menu bar.
SVMenuNode* popup_menu = BuildPopupMenu();
popup_menu->BuildMenu(window_,false);
SVMenuNode* bar_menu = BuildMenuBar();
bar_menu->BuildMenu(window_,true);
// Set the initial color values to White (could also be done by
// passing (rgb[0], rgb[1], rgb[2]).
window_->Pen(ScrollView::WHITE);
window_->Brush(ScrollView::WHITE);
// Adds the event handler to the window. This actually ensures that Notify
// gets called when events occur.
window_->AddEventHandler(this);
// Set the window visible (calling this is important to actually render
// everything. Without this call, the window would also be drawn, but the
// menu bars would be missing.
window_->SetVisible(true);
// Rest this thread until its window is destroyed.
// Note that a special eventhandling thread was created when constructing
// the window. Due to this, the application will not deadlock here.
window_->AwaitEvent(SVET_DESTROY);
// We now have 3 Threads running:
// (1) The MessageReceiver thread which fetches messages and distributes them
// (2) The EventHandler thread which handles all events for window_
// (3) The main thread which waits on window_ for a DESTROY event (blocked)
}
// If a parameter is given, we try to connect to the given server.
// This enables us to test the remote capabilities of ScrollView.
int main(int argc, char** argv) {
const char* server_name;
if (argc > 1) { server_name = argv[1]; } else { server_name = "localhost"; }
SVPaint svp(server_name);
}
#endif // GRAPHICS_DISABLED