]> git.saurik.com Git - wxWidgets.git/blob - utils/screenshotgen/src/autocapture.cpp
other cleanup; adjusted english in the UI
[wxWidgets.git] / utils / screenshotgen / src / autocapture.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: autocapture.cpp
3 // Purpose: Implement wxCtrlMaskOut class
4 // Author: Utensil Candel (UtensilCandel@@gmail.com)
5 // RCS-ID: $Id$
6 // Licence: wxWindows license
7 /////////////////////////////////////////////////////////////////////////////
8
9 // For compilers that support precompilation, includes "wx/wx.h".
10 #include "wx/wxprec.h"
11
12 #ifdef __BORLANDC__
13 #pragma hdrstop
14 #endif
15
16 // for all others, include the necessary headers
17 #ifndef WX_PRECOMP
18 #include "wx/wx.h"
19 #endif
20
21 #include <wx/filename.h>
22
23 #include "autocapture.h"
24
25
26 wxBitmap Capture(int x, int y, int width, int height)
27 {
28 //Somehow wxScreenDC.Blit() doesn't work under Mac for now. Here is a trick.
29 #ifdef __WXMAC__
30
31 //wxExecute(_T("screencapture -x ") + tempfile, wxEXEC_SYNC);
32
33 system("screencapture -x /tmp/wx_screen_capture.png");
34
35 wxBitmap fullscreen;
36
37 do
38 {
39 fullscreen = wxBitmap(_T("/tmp/wx_screen_capture.png"), wxBITMAP_TYPE_PNG);
40 }
41 while(!fullscreen.IsOk());
42
43 wxBitmap screenshot = fullscreen.GetSubBitmap(wxRect(x,y,width,height));
44
45 #else //Under other paltforms, take a real screenshot
46
47 //Create a DC for the whole screen area
48 wxScreenDC dcScreen;
49
50 //Create a Bitmap that will later on hold the screenshot image
51 //Note that the Bitmap must have a size big enough to hold the screenshot
52 //-1 means using the current default colour depth
53 wxBitmap screenshot(width, height, -1);
54
55 //Create a memory DC that will be used for actually taking the screenshot
56 wxMemoryDC memDC;
57 //Tell the memory DC to use our Bitmap
58 //all drawing action on the memory DC will go to the Bitmap now
59 memDC.SelectObject(screenshot);
60 //Blit (in this case copy) the actual screen on the memory DC
61 //and thus the Bitmap
62 memDC.Blit( 0, //Copy to this X coordinate
63 0, //Copy to this Y coordinate
64 width, //Copy this width
65 height, //Copy this height
66 &dcScreen, //From where do we copy?
67 x, //What's the X offset in the original DC?
68 y //What's the Y offset in the original DC?
69 );
70 //Select the Bitmap out of the memory DC by selecting a new
71 //uninitialized Bitmap
72 memDC.SelectObject(wxNullBitmap);
73 #endif //#ifdef __WXMAC__
74
75 // wxMessageBox(_(""),_(""));
76
77 return screenshot;
78
79 }
80
81 wxBitmap Capture(wxRect rect)
82 {
83 wxPoint origin = rect.GetPosition();
84 return Capture(origin.x, origin.y, rect.GetWidth(), rect.GetHeight());
85 }
86
87
88 // ----------------------------------------------------------------------------
89 // AutoCaptureMechanism
90 // ----------------------------------------------------------------------------
91
92 void AutoCaptureMechanism::CaptureAll()
93 {
94 m_notebook->SetSelection(0);
95 wxYield();
96
97 for(ControlList::iterator it = m_controlList.begin();
98 it != m_controlList.end();
99 ++it)
100 {
101 Control & ctrl = *it;
102
103 if(ctrl.flag == AJ_TurnPage) // Turn to next page
104 {
105 m_notebook->SetSelection(m_notebook->GetSelection() + 1);
106 wxYield();
107 continue;
108 }
109
110 wxBitmap screenshot = Capture(ctrl);
111
112 if(ctrl.flag & AJ_Union)
113 {
114 screenshot = Union(screenshot, Capture(*(++it)));
115 }
116
117 Save(screenshot, ctrl.name);
118 }
119 }
120
121 wxBitmap AutoCaptureMechanism::Capture(Control & ctrl)
122 {
123 if(ctrl.name == wxT("")) //no mannual specification for the control name
124 {
125 //Get name from wxRTTI
126 ctrl.name = ctrl.ctrl->GetClassInfo()->GetClassName();
127 }
128
129 int choice = wxNO;
130
131 if(ctrl.flag & AJ_Dropdown)
132 {
133 wxString caption = _("Do you wish to capture the dropdown list of ") + ctrl.name + _("?");
134 wxString notice = _("Click YES to capture it.\nAnd you MUST drop down the ") + ctrl.name + _(" in 3 seconds after close me.\n");
135 notice += _("Click NO otherwise.");
136
137 choice = wxMessageBox(notice, caption, wxYES_NO, m_notebook);
138
139 if(choice == wxYES)
140 {
141 //Wait for 3 seconds
142 using std::clock;
143 using std::clock_t;
144
145 clock_t start = clock();
146 while(clock() - start < CLOCKS_PER_SEC * 3)
147 {
148 wxYieldIfNeeded();
149 }
150 }
151 }
152
153 wxRect rect = GetRect(ctrl.ctrl, ctrl.flag);
154
155 //Do some rect adjust so it can include the dropdown list
156 //Currently it only works well under MSW, not adjusted for Linux and Mac OS
157 if(ctrl.flag & AJ_Dropdown && choice == wxYES)
158 {
159 // #ifdef __WXMSW__
160 int h = rect.GetHeight();
161 rect.SetHeight(h * 4);
162 // #endif
163 }
164
165 //cut off "wx" and change them into lowercase.
166 // e.g. wxButton will have a name of "button" at the end
167 ctrl.name.StartsWith(_T("wx"), &(ctrl.name));
168 ctrl.name.MakeLower();
169
170 wxBitmap screenshot = ::Capture(rect);
171
172 if(ctrl.flag & AJ_RegionAdjust)
173 {
174 PutBack(ctrl.ctrl);
175 }
176
177 return screenshot;
178 }
179
180 //if AJ_RegionAdjust is specified, the following line will use the label trick to adjust
181 //the region position and size
182 wxRect GetRect(wxWindow* ctrl, int flag);
183 //put the control back after the label trick(Using reparent/resizer approach)
184 void PutBack(wxWindow * ctrl);
185
186 wxBitmap AutoCaptureMechanism::Union(wxBitmap pic1, wxBitmap pic2)
187 {
188 int w1, w2, h1, h2, w, h;
189 w1 = pic1.GetWidth();
190 w2 = pic2.GetWidth();
191 h1 = pic1.GetHeight();
192 h2 = pic2.GetHeight();
193
194 const int gap_between = 20;
195
196 w = (w1 >= w2) ? w1 : w2;
197 h = h1 + h2 + gap_between;
198
199 wxBitmap result(w, h, -1);
200
201 wxMemoryDC dstDC;
202 dstDC.SelectObject(result);
203
204 dstDC.DrawBitmap(pic1, 0, 0, false);
205 dstDC.DrawBitmap(pic2, 0, h1 + gap_between, false);
206
207 dstDC.SelectObject(wxNullBitmap);
208
209 wxMemoryDC maskDC;
210 wxBitmap mask(w, h, 1);
211 maskDC.SelectObject(mask);
212
213 maskDC.SetPen(*wxTRANSPARENT_PEN);
214 maskDC.SetBrush(*wxBLACK_BRUSH);
215 maskDC.DrawRectangle(0, 0, w + 1, h + 1);
216
217 maskDC.SetBrush(*wxWHITE_BRUSH);
218 maskDC.DrawRectangle(0, 0, w1, h1);
219 maskDC.DrawRectangle(0, h1 + gap_between, w2, h2);
220 maskDC.SelectObject(wxNullBitmap);
221
222 result.SetMask(new wxMask(mask));
223
224 return result;
225 }
226
227 void AutoCaptureMechanism::Save(wxBitmap screenshot, wxString fileName)
228 {
229 //Check if m_defaultDir already existed
230 if(!wxDirExists(m_dir))
231 wxMkdir(m_dir);
232
233 wxString fullFileName = m_dir + wxFileName::GetPathSeparator() + fileName;
234
235 //to prvent overwritten
236 while(wxFileName::FileExists(fullFileName + _T(".png"))) fullFileName += _T("_");
237
238 //Our Bitmap now has the screenshot, so let's save it as an png
239 //The filename itself is without extension.
240 screenshot.SaveFile(fullFileName + _T(".png"), wxBITMAP_TYPE_PNG);
241 }
242
243 wxRect AutoCaptureMechanism::GetRect(wxWindow* ctrl, int flag)
244 {
245 if(flag & AJ_RegionAdjust)
246 {
247 wxWindow * parent = ctrl->GetParent();
248 wxSizer * sizer = parent->GetSizer();
249
250 if(sizer)
251 {
252 sizer->Detach(ctrl);
253
254 /*
255 +---------+-----------+---------+
256 | 0 | label | 1 |
257 +---------+-----------+---------+
258 | label | ctrl | label |
259 +---------+-----------+---------+
260 | 2 | label | 3 |
261 +---------+-----------+---------+
262 */
263
264 m_grid = new wxFlexGridSizer(3, 3, m_border, m_border);
265
266 wxStaticText* l[4];
267
268 for(int i = 0; i < 4; ++i)
269 l[i] = new wxStaticText(parent, wxID_ANY, wxT(" "));
270
271 m_grid->Add(l[0]);
272 m_grid->Add(new wxStaticText(parent, wxID_ANY, wxT(" ")));
273 m_grid->Add(l[1]);
274 m_grid->Add(new wxStaticText(parent, wxID_ANY, wxT(" ")));
275 m_grid->Add(ctrl);
276 m_grid->Add(new wxStaticText(parent, wxID_ANY, wxT(" ")));
277 m_grid->Add(l[2]);
278 m_grid->Add(new wxStaticText(parent, wxID_ANY, wxT(" ")));
279 m_grid->Add(l[3]);
280
281 sizer->Add(m_grid);
282 parent->SetSizer(sizer);
283 parent->Layout();
284
285 parent->Refresh();
286 wxYield();
287
288 return wxRect(l[0]->GetScreenRect().GetBottomRight(),
289 l[3]->GetScreenRect().GetTopLeft());
290
291 }
292 else //Actually it won't get here working with the current guiframe.h/guiframe.cpp
293 {
294 return ctrl->GetScreenRect().Inflate(m_border);
295 }
296 }
297 else
298 {
299 return ctrl->GetScreenRect().Inflate(m_border);
300 }
301 }
302
303 void AutoCaptureMechanism::PutBack(wxWindow * ctrl)
304 {
305 m_grid->Detach(ctrl);
306
307 wxSizerItemList children = m_grid->GetChildren();
308
309 for(wxSizerItemList::iterator it = children.begin(); it != children.end(); ++it)
310 {
311 wxSizerItem* item = *it;
312 if(item->IsWindow()) delete (*it)->GetWindow();
313 }
314
315 wxSizer * sizer = ctrl->GetParent()->GetSizer();
316 sizer->Detach(m_grid);
317 delete m_grid;
318 sizer->Add(ctrl);
319 }
320