1 /** \file wxsimagelist.cpp
2 *
3 * This file is part of wxSmith plugin for Code::Blocks Studio
4 * Copyright (C) 2010 Gary Harris
5 *
6 * wxSmith is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * wxSmith is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with wxSmith. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * This code was taken from the wxSmithImage plug-in, copyright Ron Collins
20 * and released under the GPL.
21 *
22 */
23 
24 #include "wxsimagelist.h"
25 #include "../properties/wxsimagelisteditordlg.h"
26 
27 namespace
28 {
29     wxsRegisterItem<wxsImageList> Reg(_T("ImageList"), wxsTTool, _T("Tools"), 72);
30 }
31 
wxsImageList(wxsItemResData * Data)32 wxsImageList::wxsImageList(wxsItemResData *Data):
33     wxsTool(Data, &Reg.Info, 0, 0)
34 {
35     int         n;
36     wxString    ss, tt;
37     wxFileName  fn;
38 
39     m_IsBuilt = false;
40     m_ImageData.Clear();
41     m_Width   = 16;
42     m_Height  = 16;
43     m_Count   = 0;
44     m_Include = false;
45 
46     // make the absolute directory path where we store XPM image files
47     // this directory is always a sub-dir where the source code file is stored
48     fn = Data->GetSrcFileName();
49     ss = fn.GetPath((wxPATH_GET_VOLUME + wxPATH_GET_SEPARATOR));
50     n  = ss.Len();
51     ss = ss + _T("wximages") + ss[n-1];
52 
53     m_IDir = ss;
54     m_RDir = _T("./wximages/");
55     m_Base = fn.GetName();
56 }
57 
58 /*! \brief Create the initial control.
59  *
60  * \return void
61  *
62  */
OnBuildCreatingCode()63 void wxsImageList::OnBuildCreatingCode()
64 {
65     int         i;
66     wxString    inc;
67     wxString    vname;  // this variable name
68     wxString    bname;  // name of the bitmap variable
69     wxString    fbase;  // base name of XPM file without dirs or extension
70     wxString    fabs;   // absolute name of XPM file
71     wxString    frel;   // relative
72     wxString    dname;  // name of XPM data array
73     wxBitmap    bmp;    // preview bitmap saved as XPM
74     wxString    ss, tt; // general use
75 
76     // have we already been here?
77     if(m_IsBuilt){
78         return;
79     }
80     m_IsBuilt = true;
81 
82     switch(GetLanguage())
83     {
84         case wxsCPP:
85             {
86                 AddHeader(_("<wx/imaglist.h>"), GetInfo().ClassName, 0);
87 
88                 // store the XPM data someplace
89                 StoreXpmData();
90 
91                 vname = GetVarName();
92                 // if there is no data, then just make empty image and bitmap
93                 if(m_Count == 0){
94                     Codef(_T("%s = new wxImageList(%d, %d, 1);\n"), vname.wx_str(), m_Width, m_Height);
95                 }
96                 // else fill it with XPM data
97                 else{
98                     Codef(_T("%s = new wxImageList(%d, %d, %d);\n"),  vname.wx_str(), m_Width, m_Height, (m_Count + 1));
99                     for(i = 0; i < m_Count; i++) {
100                         ss.Printf(_("%s_%d_XPM"), vname.wx_str(), i);
101                         Codef(_T("%s->Add(wxBitmap(%s));\n"), vname.wx_str(), ss.wx_str());
102                     }
103                 }
104 
105                 BuildSetupWindowCode();
106                 return;
107             }
108 
109         case wxsUnknownLanguage: // fall through
110         default:
111             {
112                 wxsCodeMarks::Unknown(_T("wxsImageList::OnBuildCreatingCode"), GetLanguage());
113             }
114     }
115 }
116 
117 /*! \brief Enumerate the tool's properties.
118  *
119  * \param flags long    The control flags.
120  * \return void
121  *
122  */
OnEnumToolProperties(cb_unused long Flags)123 void wxsImageList::OnEnumToolProperties(cb_unused long Flags)
124 {
125     // starting a new build cycle
126     m_IsBuilt = false;
127     m_Context = GetCoderContext();
128 
129     // details for the image list
130     WXS_IMAGELIST(wxsImageList, m_ImageData, _T("Image List"), _T("image_list"));
131     WXS_ARRAYSTRING(wxsImageList, m_ImageData, _("Images as Text"), _T("image_text"), _T("item2"));
132     WXS_LONG(wxsImageList, m_Width,   _("Image Width"),      _T("image_width"),   16);
133     WXS_LONG(wxsImageList, m_Height,  _("Image Height"),     _T("image_height"),  16);
134     WXS_LONG(wxsImageList, m_Count,   _("Image Count"),      _T("image_count"),   0);
135     WXS_BOOL(wxsImageList, m_Include, _("Use Include File"), _T("use_include"), false);
136 };
137 
138 /*! \brief Save XPM data either in the code or in a separate header file.
139  *
140  * \param void
141  * \return void
142  *
143  */
StoreXpmData(void)144 void wxsImageList::StoreXpmData(void)
145 {
146     int         i, n;
147     long        ll;
148     wxString    vname;
149     wxString    xname;
150     wxString    ss, tt, vv;
151     wxFile      ff;
152 
153     // important names
154     vname = GetVarName();
155 
156     // if no XPM images, then just store the image size
157     n = m_ImageData.GetCount();
158     if(n <= 2){
159         if(m_Width <= 0) m_Width = 16;
160         if(m_Height <= 0) m_Height = 16;
161         m_Count = 0;
162 
163         m_ImageData.Clear();
164         ss.Printf(_T("%ld"), m_Width);
165         m_ImageData.Add(ss);
166 
167         ss.Printf(_T("%ld"), m_Height);
168         m_ImageData.Add(ss);
169     }
170     // else reset the displayed size
171     else{
172         ss = m_ImageData.Item(0);
173         if(ss.ToLong(&ll)) m_Width = ll;
174 
175         ss = m_ImageData.Item(1);
176         if(ss.ToLong(&ll)) m_Height = ll;
177 
178         m_Count = 0;
179         for(i = 0;i < (int)m_ImageData.GetCount();i++){
180             ss = m_ImageData.Item(i);
181             if(ss.Find(_T("xpm_data")) >= 0){
182                 m_Count += 1;
183             }
184         };
185     };
186 
187     // are we finished?
188     if(m_Count == 0){
189         return;
190     }
191 
192     // need to create a #include file?
193     if(m_Include){
194         if(! wxFileName::DirExists(m_IDir)) wxFileName::Mkdir(m_IDir);
195         ss  = m_IDir;
196         ss += m_Base;
197         ss += _T("_");
198         ss += vname;
199         ss += _T(".xpm");
200         ff.Open(ss, wxFile::write);
201     }
202 
203     // go thru entire array, pulling out one XPM at a time into a single string
204     n = 0;
205     i = 2;
206     tt = _("");
207     while(i < (int)m_ImageData.GetCount()){
208         ss = m_ImageData.Item(i);
209         i += 1;
210 
211         // the beginning of a new XPM image means the end of the previous image
212         if(ss.Find(_T("xpm_data")) >= 0){
213             vv.Printf(_T("%s_%d_XPM"), vname.wx_str(), n);
214             ss.Replace(_T("xpm_data"), vv);
215             n += 1;
216 
217             if(tt.Length() > 0){
218                 if(m_Include){
219                     ff.Write(tt);
220                 }
221                 else{
222                     Codef(tt);
223                 }
224             }
225 
226             tt  = ss;
227             tt += _T("\n");
228         }
229         // else just another data line
230         else {
231             tt += ss;
232             tt += _T("\n");
233         }
234     }
235 
236     // the left-overs
237     if(tt.Length() > 0){
238         if(m_Include){
239             ff.Write(tt);
240         }
241         else{
242             Codef(tt);
243         }
244     }
245 
246     // include the #include file
247     if(m_Include){
248         ff.Close();
249 
250         ss = _T("\"");
251         ss += m_RDir;
252         ss += m_Base;
253         ss += _T("_");
254         ss += vname;
255         ss += _T(".xpm");
256         ss += _T("\"");
257 
258         AddHeader(ss, GetInfo().ClassName, 0);
259     }
260 }
261 
GetCount(void)262 int  wxsImageList::GetCount(void)
263 {
264     return m_Count;
265 }
266 
267 /*! \brief Get an image preview by index.
268  *
269  * \param inIndex int
270  * \return wxBitmap
271  *
272  */
GetPreview(int inIndex)273 wxBitmap wxsImageList::GetPreview(int inIndex)
274 {
275     int             i, j, n;
276     wxString        ss, tt;
277     wxArrayString   aa;
278     wxBitmap        bmp;
279 
280     // no such image?
281     if((inIndex < 0) || (inIndex >= m_Count)){
282         return wxNullBitmap;
283     }
284     if(m_ImageData.GetCount() == 0){
285         return wxNullBitmap;
286     }
287 
288     // count down to the start of that image data
289     n = -1;             // found index at start of data
290     j = 0;              // counter of data blocks
291     i = 0;              // index into m_ImageData
292 
293     while((i < (int)m_ImageData.GetCount()) && (n < 0)){
294         ss = m_ImageData.Item(i);
295         i += 1;
296 
297         if(ss.Find(_T("xpm_data")) >= 0){
298             if(j == inIndex){
299                 n = i;
300             }
301             j += 1;
302         }
303     }
304 
305     // still no data block?
306     if(n < 0){
307         return wxNullBitmap;\
308     }
309 
310     // save that first line
311     aa.Clear();
312     aa.Add(ss);
313 
314     // copy out the data block (until the next "xpm_data")
315     i = n;
316     n = -1;
317     while((i < (int)m_ImageData.GetCount()) && (n < 0)){
318         ss = m_ImageData.Item(i);
319         i += 1;
320 
321         if(ss.Find(_T("xpm_data")) >= 0){
322             n = i;
323         }
324         else{
325             aa.Add(ss);
326         }
327     }
328 
329     // turn that data block into a bitmap
330     wxsImageListEditorDlg::ArrayToBitmap(aa, bmp);
331 
332     // done
333     return bmp;
334 }
335 
336 /*! \brief Get the image list.
337  *
338  * \param aImageList wxImageList&
339  * \return void
340  *
341  */
GetImageList(wxImageList & aImageList)342 void wxsImageList::GetImageList(wxImageList &aImageList)
343 {
344     aImageList.RemoveAll();
345     wxsImageListEditorDlg::ArrayToImageList(m_ImageData, aImageList);
346 }
347 
348 /*! \brief This just exposes the "OnBuildCreatingCode()" method.
349  *
350  * \param void
351  * \return void
352  *
353  */
DoBuild(void)354 void wxsImageList::DoBuild(void)
355 {
356     BuildCode(m_Context);
357 }
358 
359