1 // ----------------------------------------------------------------------------
2 // Font_Browser.cpp v 0.0.3 2007-04-21
3 //
4 // for the Fast Light Tool Kit (FLTK) 1.1.x .
5 //
6 // David Freese, w1hkj@w1hkj.com
7 // based on similar widget by Mariwan Jalal
8 //
9 // This file is part of FLAMP.
10 //
11 // This is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This software is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //
24 // ----------------------------------------------------------------------------
25
26 #include <config.h>
27
28 #include <string>
29 #include <cstdlib>
30 #include <cstring>
31 #include <cstdio>
32 #include <stdint.h>
33
34 #include <FL/Fl.H>
35 #include <FL/Fl_Color_Chooser.H>
36 #include <FL/fl_draw.H>
37
38 #include "font_browser.h"
39 #include "flslider2.h"
40 #include "util.h"
41 #include "gettext.h"
42
43 using namespace std;
44
45 Font_Browser* font_browser;
46
47 // Font Color selected
48
ColorSelect()49 void Font_Browser::ColorSelect()
50 {
51 unsigned char r, g, b;
52 Fl::get_color(fontcolor, r, g, b);
53 if (fl_color_chooser(_("Font color"), r, g, b) == 0)
54 return;
55 fontcolor = fl_rgb_color(r, g, b);
56 btn_Color->color(fontcolor);
57 }
58
fb_callback(Fl_Widget * w,void * arg)59 void Font_Browser::fb_callback(Fl_Widget* w, void* arg)
60 {
61 Font_Browser* fb = reinterpret_cast<Font_Browser*>(arg);
62
63 if (w == fb->btn_Cancel)
64 fb->hide();
65 else if (w == fb->btn_OK) {
66 if (fb->callback_)
67 (*fb->callback_)(fb, fb->data_);
68 }
69 else if (w == fb->btn_Color)
70 fb->ColorSelect();
71 else if (w == fb->lst_Font)
72 fb->FontNameSelect();
73 else {
74 if (w == fb->lst_Size)
75 fb->txt_Size->value(strtol(fb->lst_Size->text(fb->lst_Size->value()), NULL, 10));
76 fb->fontsize = static_cast<int>(fb->txt_Size->value());
77 }
78 fb->box_Example->SetFont(fb->fontnbr, fb->fontsize, fb->fontcolor);
79 }
80
81 // Sort the font list
FontSort()82 void Font_Browser::FontSort()
83 {
84 int size = lst_Font->size();
85 for ( int t = 1; t <= size - 1; t++ )
86 for ( int r = t+1; r <= size; r++ )
87 if ( strcasecmp(lst_Font->text(t), lst_Font->text(r)) > 0 )
88 lst_Font->swap(t,r);
89 }
90
91 // Font Name changed callback
FontNameSelect()92 void Font_Browser::FontNameSelect()
93 {
94 int fn = lst_Font->value();
95 if (!fn)
96 return;
97
98 fontnbr = (Fl_Font)reinterpret_cast<intptr_t>(lst_Font->data(fn));
99
100 // get sizes and fill browser; skip first element if it is zero
101 lst_Size->clear();
102 int nsizes, *sizes;
103 size_t szt;
104 char buf[4];
105 nsizes = Fl::get_font_sizes(fontnbr, sizes);
106 //
107 for (int i = !*sizes; i < nsizes; i++)
108 if ((size_t)snprintf(buf, sizeof(buf), "%d", sizes[i]) < sizeof(buf)) {
109 szt = sizes[i];
110 lst_Size->add(buf, (void*)szt);//sizes[i]);
111 }
112
113 // scalable font with no suggested sizes
114 if (!lst_Size->size()) {
115 for (int i = 1; i <= 48; i++) {
116 snprintf(buf, sizeof(buf), "%d", i);
117 szt = i;
118 lst_Size->add(buf, (void*)szt);
119 }
120 }
121 fontSize(fontsize);
122 }
123
Font_Browser(int x,int y,int w,int h,const char * lbl)124 Font_Browser::Font_Browser(int x, int y, int w, int h, const char *lbl )
125 : Fl_Window(x, y, w, h, lbl)
126 {
127 lst_Font = new Fl_Browser(5, 15, 280, 125, _("Font:"));
128 lst_Font->align(FL_ALIGN_TOP_LEFT);
129 lst_Font->type(FL_HOLD_BROWSER);
130 lst_Font->callback(fb_callback, this);
131
132 txt_Size = new Fl_Value_Input2(290, 15, 50, 22, _("Size:"));
133 txt_Size->align(FL_ALIGN_TOP_LEFT);
134 txt_Size->range(1.0, 48.0);
135 txt_Size->step(1.0);
136 txt_Size->callback(fb_callback, this);
137
138 lst_Size = new Fl_Browser(290, 40, 50, 100);
139 lst_Size->type(FL_HOLD_BROWSER);
140 lst_Size->callback(fb_callback, this);
141
142 btn_OK = new Fl_Return_Button(345, 40, 80, 25, _("&OK"));
143 btn_OK->shortcut(0x8006f);
144 btn_OK->callback(fb_callback, this);
145
146 btn_Cancel = new Fl_Button(345, 70, 80, 25, _("Cancel"));
147 btn_Cancel->labelsize(12);
148 btn_Cancel->callback(fb_callback, this);
149
150 btn_Color = new Fl_Button(345, 100, 80, 25, _("Color"));
151 btn_Color->down_box(FL_BORDER_BOX);
152 btn_Color->color(FL_FOREGROUND_COLOR);
153 btn_Color->callback(fb_callback, this);
154
155 box_Example = new Preview_Box(5, 145, 420, 75, _("That crazy fox jumped over the dog again!\n"
156 "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789\n"
157 "!\"#$%&'()*+,-./:;<=>?@@[\\]^_`{|}~"));
158 box_Example->box(FL_DOWN_BOX);
159 box_Example->align(FL_ALIGN_WRAP|FL_ALIGN_CLIP|FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
160 resizable(box_Example);
161
162 set_modal();
163 end();
164
165 // Initializations
166
167 this->callback_ = 0; // Initialize Widgets callback
168 this->data_ = 0; // And the data
169
170 numfonts = Fl::set_fonts(0); // Nr of fonts available on the server
171
172 const char* name;
173 size_t szt;
174 for(int i = 0; i < numfonts; i++) {
175 name = Fl::get_font_name((Fl_Font)i);
176 if (isalpha(*name)) {
177 szt = i;
178 lst_Font->add(name, (void *)szt);
179 }
180 }
181 FontSort();
182
183 fontnbr = FL_HELVETICA;;
184 fontsize = FL_NORMAL_SIZE; // Font Size to be used
185 fontcolor = FL_FOREGROUND_COLOR;
186 filter = ALL_TYPES;
187
188 lst_Font->value(1);
189 FontNameSelect();
190
191 //! Fl::focus(lst_Font);
192
193 xclass(PACKAGE_NAME);
194 }
195
fontNumber(Fl_Font n)196 void Font_Browser::fontNumber(Fl_Font n)
197 {
198 fontnbr = n;
199 lst_Font->value(1);
200 int s = lst_Font->size();
201 for (int i = 1; i < s; i++ ) {
202 if ((Fl_Font)reinterpret_cast<intptr_t>(lst_Font->data(i)) == n) {
203 lst_Font->value(i);
204 FontNameSelect();
205 break;
206 }
207 }
208 }
209
fontSize(int s)210 void Font_Browser::fontSize(int s)
211 {
212 fontsize = s;
213 int n = lst_Size->size();
214 for (int i = 1; i < n; i++) {
215 if ((intptr_t)lst_Size->data(i) == fontsize) {
216 lst_Size->value(i);
217 break;
218 }
219 }
220 txt_Size->value(s);
221 }
222
fontColor(Fl_Color c)223 void Font_Browser::fontColor(Fl_Color c)
224 {
225 btn_Color->color(fontcolor = c);
226 box_Example->SetFont(fontnbr, fontsize, fontcolor);
227 box_Example->redraw();
228 }
229
fontName(const char * n)230 void Font_Browser::fontName(const char* n)
231 {
232 int s = lst_Font->size();
233 for (int i = 1; i < s; i++) {
234 if (!strcmp(lst_Font->text(i), n)) {
235 lst_Font->value(i);
236 FontNameSelect();
237 }
238 }
239 }
240
fixed_width(Fl_Font f)241 bool Font_Browser::fixed_width(Fl_Font f)
242 {
243 fl_font(f, FL_NORMAL_SIZE);
244 return fl_width('X') == fl_width('i');
245 }
246
247 #include <vector>
248 #include <FL/Fl_Double_Window.H>
249 #include <FL/Fl_Progress.H>
250
251 class Progress_Window : public Fl_Double_Window
252 {
253 public:
Progress_Window(float min=0.0f,float max=100.0f,const char * l=0)254 Progress_Window(float min = 0.0f, float max = 100.0f, const char* l = 0)
255 : Fl_Double_Window(200, 34), ps(5, 5, 190, 24, l)
256 {
257 end();
258
259 range(min, max);
260 ps.align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
261 ps.selection_color(FL_SELECTION_COLOR);
262 set_modal();
263 callback(nop);
264
265 if (l && *l) {
266 fl_font(FL_HELVETICA, FL_NORMAL_SIZE);
267 int s = (int)(fl_width(l) + fl_width('W'));
268 if (s > ps.w()) {
269 ps.size(s, ps.h());
270 size(ps.w() + 10, h());
271 }
272 }
273 position(Fl::event_x_root() - w() / 2, Fl::event_y_root() - h());
274
275 xclass(PACKAGE_TARNAME);
276 show();
277 }
range(float min,float max)278 void range(float min, float max) { ps.minimum(min); ps.maximum(max); }
value(float val)279 void value(float val) { ps.value(val); }
nop(Fl_Widget *,void *)280 static void nop(Fl_Widget*, void*) { }
281 private:
282 Fl_Progress ps;
283 };
284
fontFilter(filter_t filter)285 void Font_Browser::fontFilter(filter_t filter)
286 {
287 if (this->filter == filter)
288 return;
289
290 int s = lst_Font->size();
291
292 static vector<bool> fixed;
293 if (fixed.empty()) {
294 Progress_Window pw(1, s, _("Reading fonts..."));
295 fixed.resize(s);
296 for (int i = 1; i < s; i++) {
297 fixed[i] = fixed_width((Fl_Font)(intptr_t)(lst_Font->data(i)));
298 pw.value(i);
299 Fl::check();
300 }
301 }
302
303 switch (this->filter = filter) {
304 case FIXED_WIDTH:
305 for (int i = 1; i < s; i++) {
306 if (fixed[i])
307 lst_Font->show(i);
308 else
309 lst_Font->hide(i);
310 }
311 break;
312 case VARIABLE_WIDTH:
313 for (int i = 1; i < s; i++) {
314 if (!fixed[i])
315 lst_Font->show(i);
316 else
317 lst_Font->hide(i);
318 }
319 break;
320 case ALL_TYPES:
321 for (int i = 1; i < s; i++)
322 lst_Font->show(i);
323 break;
324 }
325 lst_Font->topline(lst_Font->value());
326 }
327
328 //////////////////////////////////////////////////////////////////////
329
Preview_Box(int x,int y,int w,int h,const char * l)330 Preview_Box::Preview_Box(int x, int y, int w, int h, const char* l)
331 : Fl_Widget(x, y, w, h, l)
332 {
333 fontName = 1;
334 fontSize = FL_NORMAL_SIZE;
335 box(FL_DOWN_BOX);
336 color(FL_BACKGROUND2_COLOR);
337 fontColor = FL_FOREGROUND_COLOR;
338 }
339
draw()340 void Preview_Box::draw()
341 {
342 draw_box();
343 fl_font((Fl_Font)fontName, fontSize);
344 fl_color(fontColor);
345 fl_draw(label(), x()+3, y()+3, w()-6, h()-6, align());
346 }
347
SetFont(int fontname,int fontsize,Fl_Color c)348 void Preview_Box::SetFont(int fontname, int fontsize, Fl_Color c)
349 {
350 fontName = fontname;
351 fontSize = fontsize;
352 fontColor = c;
353 redraw();
354 }
355