]> git.saurik.com Git - wxWidgets.git/blame - utils/screenshotgen/src/autocapture.h
No changes, just fix a typo in a comment in docview event handling code.
[wxWidgets.git] / utils / screenshotgen / src / autocapture.h
CommitLineData
0d5eda9c
FM
1/////////////////////////////////////////////////////////////////////////////
2// Name: autocapture.h
3// Purpose: Defines the AutoCaptureMechanism class
4// Author: Utensil Candel (UtensilCandel@@gmail.com)
526954c5 5// Licence: wxWindows licence
0d5eda9c
FM
6/////////////////////////////////////////////////////////////////////////////
7
f978831f
BP
8#ifndef _AUTOCAPTURE_H_
9#define _AUTOCAPTURE_H_
0d5eda9c 10
9d4aa9c2 11#include "wx/beforestd.h"
0d5eda9c 12#include <vector>
9d4aa9c2 13#include "wx/afterstd.h"
0d5eda9c 14
5f1b5e83
BP
15#include "wx/gdicmn.h"
16
17class wxBitmap;
18class wxFlexGridSizer;
19class wxWindow;
8da17c86 20class wxNotebook;
f978831f 21
17ad109b 22/**
6d6de9f1
BP
23 GlobalAdjustFlags works with AutoCaptureMechanism's constructor, to
24 configure auto-adjustments of all controls.
0d5eda9c 25
6d6de9f1
BP
26 They are used to make AutoCaptureMechanism more configurable and provide a
27 fallback to detect the bugs that the adjustments intended to avoid.
17ad109b
FM
28
29 @see AdjustFlags
30*/
31enum GlobalAdjustFlags
32{
33 /**
34 This is the default. All adjustments instructed in
35 AutoCaptureMechanism::RegisterControl() will be performed.
36 */
37 AJ_NormalAll = 0,
38
39 /**
40 Disable region adjustment for all controls.
41 */
42 AJ_DisableRegionAdjust = 1 << 0,
43
44 /**
45 Enable region adjustment for all controls.
8da17c86 46
6d6de9f1
BP
47 If AJ_DisableRegionAdjust and AJ_AlwaysRegionAdjust are both specified,
48 current implemetation will ignore AJ_DisableRegionAdjust.
17ad109b
FM
49 */
50 AJ_AlwaysRegionAdjust = 1 << 1,
51
52 /**
53 Disable name adjustment for all controls.
54 */
55 AJ_DisableNameAdjust = 1 << 2,
56
57 /**
6d6de9f1
BP
58 For all the "Drop-down Controls", e.g. wxChoice, do not prompt the user
59 about whether to capture their drop-down state, and always capture only
60 its non-drop-down state.
17ad109b
FM
61 */
62 AJ_DisableDropdown = 1 << 3
63};
64
65/**
6d6de9f1
BP
66 AdjustFlags works with AutoCaptureMechanism::RegisterControl() to specify
67 how to adjust the screenshot of the current control.
17ad109b
FM
68
69 They are used to avoid bugs, look better or interact with user etc.
70
71 @see GlobalAdjustFlags
72*/
0d5eda9c
FM
73enum AdjustFlags
74{
17ad109b
FM
75 /**
76 This is the default. Perform no adjustment for this control.
77 */
0d5eda9c 78 AJ_Normal = 0,
17ad109b
FM
79
80 /**
81 Perform region adjustment for this control.
82
6d6de9f1
BP
83 On some platforms and for some controls, wxWindow::GetScreenRect() will
84 return a smaller or deflected region. In these cases, the screenshots
85 we get are incomplete. It's recommended for everyone to fix the
86 controls' code, yet this flag provides a workaround to get a guaranteed
87 correct region without using wxWindow::GetScreenRect().
17ad109b 88
6d6de9f1
BP
89 This workaround ("label trick") is inspired by (or say stolen from)
90 Auria's work.
17ad109b 91 */
0d5eda9c 92 AJ_RegionAdjust = 1 << 0,
17ad109b
FM
93
94 /**
6d6de9f1
BP
95 This flag provides a way to capture the drop-down state of "Drop-down
96 Controls", e.g. wxChoice.
17ad109b 97
6d6de9f1
BP
98 For all the "Drop-down Controls", prompt the user about whether to
99 capture their drop-down state, if the user chooses YES, he should drop
100 down the control in about 3 seconds and wait util it's captured in that
101 state.
17ad109b 102 */
0d5eda9c 103 AJ_Dropdown = 1 << 1,
17ad109b
FM
104
105 /**
6d6de9f1
BP
106 This flag is used internally by RegisterPageTurn(). Don't use it
107 directly unless you know what you are doing.
17ad109b 108 */
0d5eda9c 109 AJ_TurnPage = 1 << 2,
17ad109b
FM
110
111 /**
6d6de9f1
BP
112 This flag provides a functionality to union screenshots of different
113 modes/states of a control into one image. e.g. the single-line /
114 multi-line modes of a wxTextCtrl.
17ad109b 115
6d6de9f1
BP
116 For a series of controls to be unioned, you should specify AJ_Union for
117 the first, and AJ_UnionEnd for the last. For the controls between them,
118 you can either specify AJ_Union or not.
8da17c86 119
6d6de9f1
BP
120 The filename of the generated screenshot is the name of the first
121 control in the series.
17ad109b 122 */
0d5eda9c 123 AJ_Union = 1 << 3,
17ad109b
FM
124
125 /**
126 @see AJ_Union.
127 */
0d5eda9c
FM
128 AJ_UnionEnd = 1 << 4
129};
130
17ad109b
FM
131/**
132 @class AutoCaptureMechanism
133
6d6de9f1 134 AutoCaptureMechanism provides an easy-to-use and adjustable facility to
4da0f1bb 135 take the screenshots for all controls fully automatically and correctly. It
6d6de9f1
BP
136 also provides an advanced feature to union screenshots of different
137 states/modes of a control.
17ad109b
FM
138
139 @section tag_filename_convention Screenshot File Name Convention
140
6d6de9f1
BP
141 All screenshots are generated as PNG files. For a control named wxName, its
142 screenshot file name would be "name.png", e.g. "button.png" for wxButton.
143 This is the protocol with the doxygen document of wxWidgets.
17ad109b 144
6d6de9f1
BP
145 By default, screenshots are generated under the subdirectory "screenshots"
146 of current working directory. During updating or adding new screenshots,
147 first make sure screenshots are generated correctly, and then copy them to
e7054054 148 the "docs/doxygen/images" folder directly.
17ad109b
FM
149
150 @section tag_gui_assumption The Assumption of GUI
151
6d6de9f1 152 Unfortunately, this class have an assumption about the structure of GUI: It
4da0f1bb 153 must have the following top-down structure:
17ad109b
FM
154
155 wxNotebook->wxPanel->wxSizer->wxControl
156
6d6de9f1
BP
157 That means, in the wxNotebook associated with this class, controls that
158 needs to be taken screenshots are placed on different panels(for grouping)
4da0f1bb 159 and laid out by wxSizers.
17ad109b
FM
160
161 @section tag_tutorial Tutorial
162
4da0f1bb 163 In the construction, you should associate a wxNotebook with this class, in
6d6de9f1
BP
164 that wxNotebook, controls that needs to be captured are placed on different
165 panels(for grouping).
17ad109b 166
6d6de9f1
BP
167 When you register controls, you should do it in order: Register the
168 controls on the first panel(using RegisterControl()), and then register a
169 page turn(using RegisterPageTurn()), so this class can turn a page of the
170 wxNotebook to present the second page. And then you register the controls
171 on the second panel, then a page turn, and so on.
17ad109b 172
6d6de9f1 173 When you are done, simply call CaptureAll(), then screenshots of all
4da0f1bb 174 controls will be automatically generated.
17ad109b
FM
175
176 @section tag_autoadjust Make Use of Auto Adjustments
4bae10bd 177
6d6de9f1
BP
178 First take a look at the document of RegisterControl(), enum AdjustFlags
179 and GlobalAdjustFlags.
4bae10bd 180
6d6de9f1
BP
181 And then, ScreenshotFrame::OnCaptureAllControls() is a good example of
182 making use of auto adjustment. Taking a look at it will get you started.
17ad109b
FM
183
184 @section tag_developer_note Notes for Developers
185
186 @subsection tag_cnc CaptureAll() and Capture()
187
6d6de9f1
BP
188 The implementation of Auto Adjustments is in CaptureAll() and Capture(),
189 the code is short, quite readable and well commented, please read the codes
190 before any modification.
17ad109b 191
6d6de9f1
BP
192 If you need the class to do something sepcial for you, consider introducing
193 a new flag and implement it in them. For an operation performed on multiple
194 controls, implemente its logic in CaptureAll(), otherwise in the private
195 member Capture().
17ad109b
FM
196
197 @subsection tag_yield_issue wxYield Issues
198
6d6de9f1
BP
199 Not quite a good habit, but this class made a lot of use of wxYield() /
200 wxYieldIfNeeded(). They are used to ensure the update of GUI (e.g. the
201 page turn of wxNotebook) is done before any further screenshot-taking, or
202 to do the timing(in Delay()). Without their use, there would be subtle
203 bugs.
204
205 I've read documents about wxYield() and understand the down side of it
206 before using it. But I didn't find a better approach to do those things,
207 and I used them carefully. So please DO NOT remove any of these wxYield()s
208 unless you're sure that it won't cause problems on all of MS Windows
209 XP/Vista, Linux(Ubuntu/Fedora), Mac OS Tiger/Leopard. And please help me
210 to find a better approach, thank you :)
17ad109b 211*/
0d5eda9c
FM
212class AutoCaptureMechanism
213{
214public:
17ad109b
FM
215 /**
216 Constructor.
217
218 @param notebook
6d6de9f1
BP
219 The wxNotebook associated with this class. Please see
220 @ref tag_gui_assumption and @ref tag_tutorial.
17ad109b 221 @param flag
6d6de9f1
BP
222 It's one of or a combination of GlobalAdjustFlags, to disable /
223 enable some auto-adjustment for all controls.
17ad109b 224 @param margin
6d6de9f1 225 It's the margin around every control in the sreenshots.
17ad109b 226 */
6cd1aa9d 227 AutoCaptureMechanism(wxNotebook *notebook,
17ad109b 228 int flag = AJ_NormalAll,
5f1b5e83 229 int margin = 5);
60a2264d 230
5f1b5e83 231 ~AutoCaptureMechanism() { }
0d5eda9c 232
17ad109b
FM
233 /**
234 Register a control and perform specifid auto adjustments.
235
236 @param ctrl
6d6de9f1 237 The pointer to the control to be taken a screenshot.
17ad109b 238 @param name
6d6de9f1
BP
239 If you find out that the screenshot for this control was generated
240 under an incorrect file name, specify @a name. e.g. for wxButton,
241 "wxButton" or "button" are both OK.
17ad109b 242 @param flag
6d6de9f1
BP
243 If you end up with an a smaller or deflected screenshot, use
244 AJ_RegionAdjust.
17ad109b 245
6d6de9f1
BP
246 If you want to caputure the "drop-down" state of a "drop-down"
247 control, use AJ_Dropdown.
17ad109b 248
6d6de9f1
BP
249 If you want to present different states of a control in one
250 screenshot, use AJ_Union and AJ_UnionEnd.
17ad109b 251
6d6de9f1
BP
252 Please read the document of enum AdjustFlags, and notice that this
253 flag could be enabled / disabled by global flag GlobalAdjustFlags.
0d5eda9c 254 */
6d6de9f1
BP
255 void RegisterControl(wxWindow* ctrl,
256 wxString name = wxT(""),
257 int flag = AJ_Normal)
0d5eda9c
FM
258 {
259 m_controlList.push_back(Control(ctrl, name, flag));
260 }
261
17ad109b
FM
262 /**
263 Register a control and perform specifid auto adjustments.
264
6d6de9f1
BP
265 This calls RegisterControl(wxWindow* ctrl, wxString name, int flag)
266 with an empty name. This is useful when you only want to auto-adjust
267 something other than name adjustment.
17ad109b 268 */
6d6de9f1 269 void RegisterControl(wxWindow* ctrl, int flag)
0d5eda9c 270 {
9a83f860 271 RegisterControl(ctrl, wxT(""), flag);
0d5eda9c
FM
272 }
273
17ad109b
FM
274 /**
275 Register a page turn.
276
6d6de9f1
BP
277 When you finished registering the controls on a panel, remember to
278 call it to turn the wxNotebook to the next panel.
17ad109b 279 */
0d5eda9c
FM
280 void RegisterPageTurn()
281 {
9a83f860 282 m_controlList.push_back(Control(0, wxT(""), AJ_TurnPage));
0d5eda9c
FM
283 }
284
17ad109b
FM
285 /**
286 Capture all registered controls of the associated wxNotebook.
287 */
60a2264d 288 void CaptureAll();
0d5eda9c 289
17ad109b
FM
290 /*
291 Static Members
292 */
293 /**
294 Take a screenshot for the given region.
295
07e6fc43
BP
296 @param bitmap
297 Bitmap to save the screenshot to.
5f1b5e83 298 @param rect
07e6fc43 299 Given rectangular region.
5f1b5e83 300 @param delay
07e6fc43
BP
301 Only useful for Mac, for fixing a delay bug. It seems that it
302 didn't fix the bug, so it might be removed soon.
17ad109b 303 */
5f1b5e83 304 static bool Capture(wxBitmap* bitmap, wxRect rect, int delay = 0);
17ad109b
FM
305
306 /**
307 Take a screenshot for the given region.
308
5f1b5e83 309 @see Capture(wxBitmap*,wxRect,int)
17ad109b 310 */
6d6de9f1
BP
311 static bool Capture(wxBitmap* bitmap,
312 int x, int y, int width, int height,
313 int delay = 0);
6cd1aa9d 314
17ad109b 315 /**
6d6de9f1
BP
316 Save the screenshot as the name of @a fileName in the default
317 directory.
17ad109b
FM
318
319 @a fileName should be without ".png".
320 */
5f1b5e83 321 static void Save(wxBitmap* screenshot, const wxString& fileName);
17ad109b
FM
322
323 /**
324 Set the default directory where the screenshots will be generated.
325 */
5f1b5e83 326 static void SetDefaultDirectory(const wxString& dir) { default_dir = dir; }
17ad109b
FM
327
328 /**
329 Get the default directory where the screenshots will be generated.
330 */
331 static wxString GetDefaultDirectory() { return default_dir; }
332
333 /**
6d6de9f1
BP
334 Get the absolute path of the default directory where the screenshots
335 will be generated.
17ad109b 336 */
8da17c86 337 static wxString GetDefaultDirectoryAbsPath();
6cd1aa9d 338
17ad109b 339private:
101adcd5 340
17ad109b
FM
341 /*
342 Internal Data Structures
343
344 They might go public in future to provide reuse of ControlList.
345 */
0d5eda9c
FM
346 struct Control
347 {
348 Control() {}
349
350 Control(wxWindow * _ctrl, wxString _name, int _flag)
351 : ctrl(_ctrl), name(_name), flag(_flag) {}
352
353 wxWindow * ctrl;
354 wxString name;
355 int flag;
356 };
357
17ad109b
FM
358 typedef std::vector<Control> ControlList;
359
360 /*
361 Internal Functions
362
6d6de9f1
BP
363 They are only used to clearify the logic of some public functions and
364 it's nonsense to call them elsewhere.
17ad109b
FM
365 */
366
367 /*
368 Capture and auto adjust the control. Used by CaptureAll().
369 */
5f1b5e83 370 bool Capture(wxBitmap* bitmap, Control& ctrl);
0d5eda9c 371
17ad109b
FM
372 /*
373 Get the correct rectangular region that the control occupies. Used by
374 Capture(Control & ctrl).
375
6d6de9f1
BP
376 If AJ_RegionAdjust is specified, it will use the "label trick" to
377 perform region auto adjustment.
17ad109b 378
6d6de9f1
BP
379 The "label trick" is to reattach the control to a wxFlexGridSizer
380 m_grid, surround the control with labels and get the control's region
381 by label's positions. Just like this:
17ad109b
FM
382
383 +---------+-----------+---------+
384 | 0 | label | 1 |
385 +---------+-----------+---------+
386 | label | ctrl | label |
387 +---------+-----------+---------+
388 | 2 | label | 3 |
389 +---------+-----------+---------+
390
6d6de9f1
BP
391 So, there will be a side effect: the control is moved to a new
392 position. So after taking the screenshot, Capture(Control & ctrl)
393 should call PutBack(wxWindow * ctrl) to put it back.
17ad109b 394
6d6de9f1
BP
395 If AJ_RegionAdjust isn't specified, it will simply call
396 wxWindow::GetScreenRect().
17ad109b 397 */
0d5eda9c 398 wxRect GetRect(wxWindow* ctrl, int flag);
4bae10bd 399
17ad109b
FM
400 /*
401 Put the control back after the label trick used in GetRect(). Used by
402 Capture(Control & ctrl).
403 */
0d5eda9c
FM
404 void PutBack(wxWindow * ctrl);
405
17ad109b 406 /*
6d6de9f1
BP
407 Union two screenshots in the vertical direction, and leave a gap
408 between the screenshots. Used by CaptureAll().
17ad109b
FM
409
410 The gap is 20 pixels by default. Currently it isn't configurable.
411 */
5f1b5e83 412 static bool Union(wxBitmap* top, wxBitmap* bottom, wxBitmap* result);
0d5eda9c 413
8da17c86
FM
414 /*
415 Delay a few seconds without blocking GUI.
416 */
17ad109b 417 static void Delay(int seconds);
0d5eda9c 418
17ad109b
FM
419 /*
420 Data Members
421 */
4bae10bd 422 ControlList m_controlList;
0d5eda9c 423
4bae10bd 424 wxNotebook* m_notebook;
0d5eda9c 425
17ad109b
FM
426 int m_flag;
427
428 int m_margin;
429
4bae10bd 430 wxFlexGridSizer* m_grid;
0d5eda9c 431
17ad109b 432 static wxString default_dir;
0d5eda9c
FM
433};
434
f978831f 435#endif // _AUTOCAPTURE_H_