Bumped copyright dates for 2013
[barry.git] / desktop / src / util.cc
blobd2775f8c644921c5a52333b64bf6c069f7e88c9c
1 ///
2 /// \file util.cc
3 /// Utility functions specific to Barry Desktop
4 ///
6 /*
7 Copyright (C) 2009-2013, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "util.h"
23 #include "barrydesktop.h"
24 #include "windowids.h"
25 #include <wx/datectrl.h>
26 #include <wx/tokenzr.h>
27 #include <algorithm>
28 #include "wxi18n.h"
30 using namespace std;
32 const wxChar *ButtonNames[] = {
33 _T("backuprestore"),
34 _T("sync"),
35 _T("modem"),
36 _T("migratedevice"),
37 _T("browsedatabases"),
38 _T("apploader"),
39 _T("media"),
40 _T("misc"),
44 const wxArrayString& GetButtonLabels()
46 static wxArrayString m_labels;
48 if( m_labels.GetCount() == 0 ) {
49 // TRANSLATORS: this is a main screen button label. See
50 // util.cc line 200 for more information on its flexibility.
51 m_labels.Add( _W("Backup &\nRestore") );
52 // TRANSLATORS: this is a main screen button label
53 m_labels.Add( _W("Sync") );
54 // TRANSLATORS: this is a main screen button label
55 m_labels.Add( _W("Modem\nTethering") );
56 // TRANSLATORS: this is a main screen button label
57 m_labels.Add( _W("Migrate\nDevice") );
58 // TRANSLATORS: this is a main screen button label
59 m_labels.Add( _W("Browse\nDatabases") );
60 // TRANSLATORS: this is a main screen button label
61 m_labels.Add( _W("Application\nLoader") );
62 // TRANSLATORS: this is a main screen button label
63 m_labels.Add( _W("Media") );
64 // TRANSLATORS: this is a main screen button label
65 m_labels.Add( _W("Misc") );
68 return m_labels;
71 bool ButtonEnabled[] = {
72 true, // backuprestore
73 true, // sync
74 true, // modem
75 true, // migratedevice
76 true, // browsedatabases
77 false, // apploader
78 false, // media
79 false, // misc
80 false
83 const wxChar *StateNames[] = {
84 _T("-normal.png"),
85 _T("-focus.png"),
86 _T("-pushed.png"),
90 //////////////////////////////////////////////////////////////////////////////
91 // Utility functions
93 std::string GetBaseFilename(const std::string &filename)
95 std::string file = BARRYDESKTOP_BASEDATADIR;
96 file += filename;
97 if( wxFileExists(wxString(file.c_str(), wxConvUTF8)) )
98 return file;
100 // fall back to the devel tree
101 return filename;
104 /// Returns full path and filename for given filename.
105 /// 'filename' should have no directory component, as the
106 /// directory will be prepended and returned.
107 wxString GetImageFilename(const wxString &filename)
109 // try the official install directory first
110 wxString file = _T(BARRYDESKTOP_IMAGEDIR);
111 file += filename;
112 if( wxFileExists(file) )
113 return file;
115 // oops, assume we're running from the build directory,
116 // and use the images dir
117 file = wxPathOnly(wxGetApp().argv[0]);
118 file += _T("/../images/");
119 file += filename;
120 if( wxFileExists(file) )
121 return file;
123 // hmmm.... maybe we're running from inside the libtool
124 // build subdirectories
125 file = wxPathOnly(wxGetApp().argv[0]);
126 file += _T("/../../images/");
127 file += filename;
128 return file;
131 wxString GetButtonFilename(int id, int state)
133 return GetImageFilename(
134 wxString(ButtonNames[id - MainMenu_FirstButton]) +
135 StateNames[state]
139 wxString GetButtonLabel(int id)
141 return GetButtonLabels()[id - MainMenu_FirstButton];
144 bool IsButtonEnabled(int id)
146 return ButtonEnabled[id - MainMenu_FirstButton];
149 void MakeDateRecent(bool checked, wxDatePickerCtrl *picker)
151 wxDateTime when = picker->GetValue();
152 if( checked && (!when.IsValid() ||
153 when < wxDateTime(1, wxDateTime::Jan, 1975, 0, 0, 0)) )
155 when = wxDateTime::Now();
156 picker->SetValue(when);
160 bool IsParsable(const std::string &dbname)
162 #undef HANDLE_PARSER
163 #define HANDLE_PARSER(dbn) \
164 if( dbname == Barry::dbn::GetDBName() ) return true;
166 ALL_KNOWN_PARSER_TYPES
168 return false;
171 bool IsBuildable(const std::string &dbname)
173 #undef HANDLE_BUILDER
174 #define HANDLE_BUILDER(dbn) \
175 if( dbname == Barry::dbn::GetDBName() ) return true;
177 ALL_KNOWN_BUILDER_TYPES
179 return false;
182 namespace {
183 struct LabelLine
185 wxString m_line;
186 int m_width;
187 int m_height;
189 LabelLine(const wxString &line, const wxDC &dc)
190 : m_line(line)
191 , m_width(0)
192 , m_height(0)
194 dc.GetTextExtent(line, &m_width, &m_height);
200 // DrawButtonLabel
202 /// Draws the given label text in the specified area of the bitmap,
203 /// modifying the DC in the process (the bitmap is only used for
204 /// sizing). This is intended for use in creating the main Desktop
205 /// buttons, but can be used on any image.
207 /// The left/top/right/bottom coordinates are relative to the 0,0 of
208 /// the bitmap itself, and limit the area where the label text will be
209 /// drawn. If -1 is used for any of the values, the bitmap edge will
210 /// be used. If other negative numbers are used, (edge - value) will
211 /// be used.
213 /// The label text can contain \n characters to split into multiple
214 /// lines. Each line will be centered (left/right) in the coordinate
215 /// area, and all lines will be centered (top/bottom) in the coordinate
216 /// area. A trailing \n character is not required, and not recommended.
218 /// If the coordinate area is too small for the given text and font,
219 /// the font will be reduced iteratively for a few points and tried again.
220 /// If still too big, a DrawButtonLabelError exception will be thrown.
221 /// Note that the font passed in will be modified in this case, in case
222 /// the new point size needs to be used elsewhere.
224 /// If the label contains an empty string, a DrawButtonLabelError exception will
225 /// be thrown. This is to prevent any unlabeled buttons in the system.
227 /// If Font is invalid, DrawButtonLabelError will be thrown.
229 void DrawButtonLabelDC(wxDC &dc, const wxBitmap &bmp, const wxString &label,
230 wxFont &font, const wxColour &textfg,
231 int left, int top, int right, int bottom)
233 // calculate the coordinates, and various sanity checks
234 if( left == -1 ) left = 0;
235 if( top == -1 ) top = 0;
236 if( right == -1 ) right = bmp.GetWidth();
237 if( bottom == -1 ) bottom = bmp.GetHeight();
239 if( right < -1 ) right = bmp.GetWidth() + right;
240 if( bottom < -1 ) bottom = bmp.GetHeight() + bottom;
242 int width = right - left;
243 if( width < 0 ) {
244 swap(left, right);
245 width = right - left;
248 int height = bottom - top;
249 if( height < 0 ) {
250 swap(top, bottom);
251 height = bottom - top;
254 if( !font.IsOk() )
255 throw DrawButtonLabelError(_C("Unable to create button: font is invalid"));
257 // create DC to work with, writing into the bitmap given to us
258 dc.SetFont(font);
259 dc.SetTextForeground(textfg);
260 dc.SetMapMode(wxMM_TEXT);
262 // build vector of lines, and calculate totals
263 int total_text_height = 0;
264 int widest_line = 0;
265 std::vector<LabelLine> lines;
267 // ... and keep trying if too big
268 for( int tries = 0; ; tries++ ) {
269 // start fresh
270 total_text_height = 0;
271 widest_line = 0;
272 lines.clear();
274 wxStringTokenizer tokens(label, _T("\n"));
275 while( tokens.HasMoreTokens() ) {
276 wxString token = tokens.GetNextToken();
277 token.Trim(true);
278 token.Trim(false);
280 if( !tokens.HasMoreTokens() && token.size() == 0 ) {
281 // we're done here... last line is empty
282 break;
285 LabelLine line(token, dc);
286 lines.push_back( line );
287 total_text_height += line.m_height;
288 widest_line = max(widest_line, line.m_width);
291 // do we have enough room?
292 if( total_text_height <= height && widest_line <= width ) {
293 // good to go!
294 break;
297 // only reduce font so much...
298 if( tries >= 4 )
299 throw DrawButtonLabelError(_C("Unable to create button: text is too big to fit: ") + string(label.utf8_str()));
301 // too big, reduce font and try again
302 font.SetPointSize( font.GetPointSize() - 1 );
303 dc.SetFont(font);
306 // empty?
307 if( lines.size() == 0 )
308 throw DrawButtonLabelError(_C("Unable to create button: label is empty"));
310 // calculate starting height
311 int y = (height - total_text_height) / 2 + top;
313 // draw each line, centering each one horizontally, and
314 // incrementing y by the line's height on each pass
315 std::vector<LabelLine>::iterator b = lines.begin(), e = lines.end();
316 for( ; b != e; ++b ) {
317 int x = (width - b->m_width) / 2 + left;
318 dc.DrawText(b->m_line, x, y);
319 y += b->m_height;