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