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