|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_get_system_colors.cxx 7903 2010-11-28 21:06:39Z matt $" 00003 // 00004 // System color support for the Fast Light Tool Kit (FLTK). 00005 // 00006 // Copyright 1998-2010 by Bill Spitzak and others. 00007 // 00008 // This library is free software; you can redistribute it and/or 00009 // modify it under the terms of the GNU Library General Public 00010 // License as published by the Free Software Foundation; either 00011 // version 2 of the License, or (at your option) any later version. 00012 // 00013 // This library is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 // Library General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU Library General Public 00019 // License along with this library; if not, write to the Free Software 00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00021 // USA. 00022 // 00023 // Please report all bugs and problems on the following page: 00024 // 00025 // http://www.fltk.org/str.php 00026 // 00027 00028 #include <FL/Fl.H> 00029 #include <FL/fl_draw.H> 00030 #include <FL/x.H> 00031 #include <FL/math.h> 00032 #include <FL/fl_utf8.h> 00033 #include "flstring.h" 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <FL/Fl_Pixmap.H> 00037 #include <FL/Fl_Tiled_Image.H> 00038 #include "tile.xpm" 00039 00040 #if defined(WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) 00041 // Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs 00042 // on Windows, which is supposed to be POSIX compliant... 00043 # define putenv _putenv 00044 #endif // WIN32 && !__CYGWIN__ 00045 00046 static char fl_bg_set = 0; 00047 static char fl_bg2_set = 0; 00048 static char fl_fg_set = 0; 00049 00056 void Fl::background(uchar r, uchar g, uchar b) { 00057 fl_bg_set = 1; 00058 00059 // replace the gray ramp so that FL_GRAY is this color 00060 if (!r) r = 1; else if (r==255) r = 254; 00061 double powr = log(r/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); 00062 if (!g) g = 1; else if (g==255) g = 254; 00063 double powg = log(g/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); 00064 if (!b) b = 1; else if (b==255) b = 254; 00065 double powb = log(b/255.0)/log((FL_GRAY-FL_GRAY_RAMP)/(FL_NUM_GRAY-1.0)); 00066 for (int i = 0; i < FL_NUM_GRAY; i++) { 00067 double gray = i/(FL_NUM_GRAY-1.0); 00068 Fl::set_color(fl_gray_ramp(i), 00069 uchar(pow(gray,powr)*255+.5), 00070 uchar(pow(gray,powg)*255+.5), 00071 uchar(pow(gray,powb)*255+.5)); 00072 } 00073 } 00075 void Fl::foreground(uchar r, uchar g, uchar b) { 00076 fl_fg_set = 1; 00077 00078 Fl::set_color(FL_FOREGROUND_COLOR,r,g,b); 00079 } 00080 00087 void Fl::background2(uchar r, uchar g, uchar b) { 00088 fl_bg2_set = 1; 00089 00090 Fl::set_color(FL_BACKGROUND2_COLOR,r,g,b); 00091 Fl::set_color(FL_FOREGROUND_COLOR, 00092 get_color(fl_contrast(FL_FOREGROUND_COLOR,FL_BACKGROUND2_COLOR))); 00093 } 00094 00095 // these are set by Fl::args() and override any system colors: 00096 const char *fl_fg = NULL; 00097 const char *fl_bg = NULL; 00098 const char *fl_bg2 = NULL; 00099 00100 static void set_selection_color(uchar r, uchar g, uchar b) { 00101 Fl::set_color(FL_SELECTION_COLOR,r,g,b); 00102 } 00103 00104 #if defined(WIN32) || defined(__APPLE__) 00105 00106 # include <stdio.h> 00107 // simulation of XParseColor: 00108 int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) { 00109 if (*p == '#') p++; 00110 int n = strlen(p); 00111 int m = n/3; 00112 const char *pattern = 0; 00113 switch(m) { 00114 case 1: pattern = "%1x%1x%1x"; break; 00115 case 2: pattern = "%2x%2x%2x"; break; 00116 case 3: pattern = "%3x%3x%3x"; break; 00117 case 4: pattern = "%4x%4x%4x"; break; 00118 default: return 0; 00119 } 00120 int R,G,B; if (sscanf(p,pattern,&R,&G,&B) != 3) return 0; 00121 switch(m) { 00122 case 1: R *= 0x11; G *= 0x11; B *= 0x11; break; 00123 case 3: R >>= 4; G >>= 4; B >>= 4; break; 00124 case 4: R >>= 8; G >>= 8; B >>= 8; break; 00125 } 00126 r = (uchar)R; g = (uchar)G; b = (uchar)B; 00127 return 1; 00128 } 00129 #else 00130 // Wrapper around XParseColor... 00131 int fl_parse_color(const char* p, uchar& r, uchar& g, uchar& b) { 00132 XColor x; 00133 if (!fl_display) fl_open_display(); 00134 if (XParseColor(fl_display, fl_colormap, p, &x)) { 00135 r = (uchar)(x.red>>8); 00136 g = (uchar)(x.green>>8); 00137 b = (uchar)(x.blue>>8); 00138 return 1; 00139 } else return 0; 00140 } 00141 #endif // WIN32 || __APPLE__ 00142 00154 #if defined(WIN32) 00155 static void 00156 getsyscolor(int what, const char* arg, void (*func)(uchar,uchar,uchar)) 00157 { 00158 if (arg) { 00159 uchar r,g,b; 00160 if (!fl_parse_color(arg, r,g,b)) 00161 Fl::error("Unknown color: %s", arg); 00162 else 00163 func(r,g,b); 00164 } else { 00165 DWORD x = GetSysColor(what); 00166 func(uchar(x&255), uchar(x>>8), uchar(x>>16)); 00167 } 00168 } 00169 00170 void Fl::get_system_colors() { 00171 if (!fl_bg2_set) getsyscolor(COLOR_WINDOW, fl_bg2,Fl::background2); 00172 if (!fl_fg_set) getsyscolor(COLOR_WINDOWTEXT, fl_fg, Fl::foreground); 00173 if (!fl_bg_set) getsyscolor(COLOR_BTNFACE, fl_bg, Fl::background); 00174 getsyscolor(COLOR_HIGHLIGHT, 0, set_selection_color); 00175 } 00176 00177 #elif defined(__APPLE__) 00178 // MacOS X currently supports two color schemes - Blue and Graphite. 00179 // Since we aren't emulating the Aqua interface (even if Apple would 00180 // let us), we use some defaults that are similar to both. The 00181 // Fl::scheme("plastic") color/box scheme provides a usable Aqua-like 00182 // look-n-feel... 00183 void Fl::get_system_colors() 00184 { 00185 fl_open_display(); 00186 00187 if (!fl_bg2_set) background2(0xff, 0xff, 0xff); 00188 if (!fl_fg_set) foreground(0, 0, 0); 00189 if (!fl_bg_set) background(0xd8, 0xd8, 0xd8); 00190 00191 #if 0 00192 // this would be the correct code, but it does not run on all versions 00193 // of OS X. Also, setting a bright selection color would require 00194 // some updates in Fl_Adjuster and Fl_Help_Browser 00195 OSStatus err; 00196 RGBColor c; 00197 err = GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor, 24, true, &c); 00198 if (err) 00199 set_selection_color(0x00, 0x00, 0x80); 00200 else 00201 set_selection_color(c.red, c.green, c.blue); 00202 #else 00203 set_selection_color(0x00, 0x00, 0x80); 00204 #endif 00205 } 00206 #else 00207 00208 // Read colors that KDE writes to the xrdb database. 00209 00210 // XGetDefault does not do the expected thing: it does not like 00211 // periods in either word. Therefore it cannot match class.Text.background. 00212 // However *.Text.background is matched by pretending the program is "Text". 00213 // But this will also match *.background if there is no *.Text.background 00214 // entry, requiring users to put in both (unless they want the text fields 00215 // the same color as the windows). 00216 00217 static void 00218 getsyscolor(const char *key1, const char* key2, const char *arg, const char *defarg, void (*func)(uchar,uchar,uchar)) 00219 { 00220 if (!arg) { 00221 arg = XGetDefault(fl_display, key1, key2); 00222 if (!arg) arg = defarg; 00223 } 00224 XColor x; 00225 if (!XParseColor(fl_display, fl_colormap, arg, &x)) 00226 Fl::error("Unknown color: %s", arg); 00227 else 00228 func(x.red>>8, x.green>>8, x.blue>>8); 00229 } 00230 00231 void Fl::get_system_colors() 00232 { 00233 fl_open_display(); 00234 const char* key1 = 0; 00235 if (Fl::first_window()) key1 = Fl::first_window()->xclass(); 00236 if (!key1) key1 = "fltk"; 00237 if (!fl_bg2_set) getsyscolor("Text","background", fl_bg2, "#ffffff", Fl::background2); 00238 if (!fl_fg_set) getsyscolor(key1, "foreground", fl_fg, "#000000", Fl::foreground); 00239 if (!fl_bg_set) getsyscolor(key1, "background", fl_bg, "#c0c0c0", Fl::background); 00240 getsyscolor("Text", "selectBackground", 0, "#000080", set_selection_color); 00241 } 00242 00243 #endif 00244 00245 00247 #define D1 BORDER_WIDTH 00248 #define D2 (BORDER_WIDTH+BORDER_WIDTH) 00249 00250 extern void fl_up_box(int, int, int, int, Fl_Color); 00251 extern void fl_down_box(int, int, int, int, Fl_Color); 00252 extern void fl_thin_up_box(int, int, int, int, Fl_Color); 00253 extern void fl_thin_down_box(int, int, int, int, Fl_Color); 00254 extern void fl_round_up_box(int, int, int, int, Fl_Color); 00255 extern void fl_round_down_box(int, int, int, int, Fl_Color); 00256 00257 extern void fl_up_frame(int, int, int, int, Fl_Color); 00258 extern void fl_down_frame(int, int, int, int, Fl_Color); 00259 extern void fl_thin_up_frame(int, int, int, int, Fl_Color); 00260 extern void fl_thin_down_frame(int, int, int, int, Fl_Color); 00261 00262 #ifndef FL_DOXYGEN 00263 const char *Fl::scheme_ = (const char *)0; // current scheme 00264 Fl_Image *Fl::scheme_bg_ = (Fl_Image *)0; // current background image for the scheme 00265 #endif 00266 00267 static Fl_Pixmap tile(tile_xpm); 00268 00288 int Fl::scheme(const char *s) { 00289 if (!s) { 00290 if ((s = getenv("FLTK_SCHEME")) == NULL) { 00291 #if !defined(WIN32) && !defined(__APPLE__) 00292 const char* key = 0; 00293 if (Fl::first_window()) key = Fl::first_window()->xclass(); 00294 if (!key) key = "fltk"; 00295 fl_open_display(); 00296 s = XGetDefault(fl_display, key, "scheme"); 00297 #endif // !WIN32 && !__APPLE__ 00298 } 00299 } 00300 00301 if (s) { 00302 if (!strcasecmp(s, "none") || !strcasecmp(s, "base") || !*s) s = 0; 00303 else s = strdup(s); 00304 } 00305 if (scheme_) free((void*)scheme_); 00306 scheme_ = s; 00307 00308 // Save the new scheme in the FLTK_SCHEME env var so that child processes 00309 // inherit it... 00310 static char e[1024]; 00311 strcpy(e,"FLTK_SCHEME="); 00312 if (s) strlcat(e,s,sizeof(e)); 00313 putenv(e); 00314 00315 // Load the scheme... 00316 return reload_scheme(); 00317 } 00318 00319 int Fl::reload_scheme() { 00320 Fl_Window *win; 00321 00322 if (scheme_ && !strcasecmp(scheme_, "plastic")) { 00323 // Update the tile image to match the background color... 00324 uchar r, g, b; 00325 int nr, ng, nb; 00326 int i; 00327 // static uchar levels[3] = { 0xff, 0xef, 0xe8 }; 00328 // OSX 10.3 and higher use a background with less contrast... 00329 static uchar levels[3] = { 0xff, 0xf8, 0xf4 }; 00330 00331 get_color(FL_GRAY, r, g, b); 00332 00333 // printf("FL_GRAY = 0x%02x 0x%02x 0x%02x\n", r, g, b); 00334 00335 for (i = 0; i < 3; i ++) { 00336 nr = levels[i] * r / 0xe8; 00337 if (nr > 255) nr = 255; 00338 00339 ng = levels[i] * g / 0xe8; 00340 if (ng > 255) ng = 255; 00341 00342 nb = levels[i] * b / 0xe8; 00343 if (nb > 255) nb = 255; 00344 00345 sprintf(tile_cmap[i], "%c c #%02x%02x%02x", "Oo."[i], nr, ng, nb); 00346 // puts(tile_cmap[i]); 00347 } 00348 00349 tile.uncache(); 00350 00351 if (!scheme_bg_) scheme_bg_ = new Fl_Tiled_Image(&tile, w(), h()); 00352 00353 // Load plastic buttons, etc... 00354 set_boxtype(FL_UP_FRAME, FL_PLASTIC_UP_FRAME); 00355 set_boxtype(FL_DOWN_FRAME, FL_PLASTIC_DOWN_FRAME); 00356 set_boxtype(FL_THIN_UP_FRAME, FL_PLASTIC_UP_FRAME); 00357 set_boxtype(FL_THIN_DOWN_FRAME, FL_PLASTIC_DOWN_FRAME); 00358 00359 set_boxtype(FL_UP_BOX, FL_PLASTIC_UP_BOX); 00360 set_boxtype(FL_DOWN_BOX, FL_PLASTIC_DOWN_BOX); 00361 set_boxtype(FL_THIN_UP_BOX, FL_PLASTIC_THIN_UP_BOX); 00362 set_boxtype(FL_THIN_DOWN_BOX, FL_PLASTIC_THIN_DOWN_BOX); 00363 set_boxtype(_FL_ROUND_UP_BOX, FL_PLASTIC_ROUND_UP_BOX); 00364 set_boxtype(_FL_ROUND_DOWN_BOX, FL_PLASTIC_ROUND_DOWN_BOX); 00365 00366 // Use standard size scrollbars... 00367 Fl::scrollbar_size(16); 00368 } else if (scheme_ && !strcasecmp(scheme_, "gtk+")) { 00369 // Use a GTK+ inspired look-n-feel... 00370 if (scheme_bg_) { 00371 delete scheme_bg_; 00372 scheme_bg_ = (Fl_Image *)0; 00373 } 00374 00375 set_boxtype(FL_UP_FRAME, FL_GTK_UP_FRAME); 00376 set_boxtype(FL_DOWN_FRAME, FL_GTK_DOWN_FRAME); 00377 set_boxtype(FL_THIN_UP_FRAME, FL_GTK_THIN_UP_FRAME); 00378 set_boxtype(FL_THIN_DOWN_FRAME, FL_GTK_THIN_DOWN_FRAME); 00379 00380 set_boxtype(FL_UP_BOX, FL_GTK_UP_BOX); 00381 set_boxtype(FL_DOWN_BOX, FL_GTK_DOWN_BOX); 00382 set_boxtype(FL_THIN_UP_BOX, FL_GTK_THIN_UP_BOX); 00383 set_boxtype(FL_THIN_DOWN_BOX, FL_GTK_THIN_DOWN_BOX); 00384 set_boxtype(_FL_ROUND_UP_BOX, FL_GTK_ROUND_UP_BOX); 00385 set_boxtype(_FL_ROUND_DOWN_BOX, FL_GTK_ROUND_DOWN_BOX); 00386 00387 // Use slightly thinner scrollbars... 00388 Fl::scrollbar_size(15); 00389 } else { 00390 // Use the standard FLTK look-n-feel... 00391 if (scheme_bg_) { 00392 delete scheme_bg_; 00393 scheme_bg_ = (Fl_Image *)0; 00394 } 00395 00396 set_boxtype(FL_UP_FRAME, fl_up_frame, D1, D1, D2, D2); 00397 set_boxtype(FL_DOWN_FRAME, fl_down_frame, D1, D1, D2, D2); 00398 set_boxtype(FL_THIN_UP_FRAME, fl_thin_up_frame, 1, 1, 2, 2); 00399 set_boxtype(FL_THIN_DOWN_FRAME, fl_thin_down_frame, 1, 1, 2, 2); 00400 00401 set_boxtype(FL_UP_BOX, fl_up_box, D1, D1, D2, D2); 00402 set_boxtype(FL_DOWN_BOX, fl_down_box, D1, D1, D2, D2); 00403 set_boxtype(FL_THIN_UP_BOX, fl_thin_up_box, 1, 1, 2, 2); 00404 set_boxtype(FL_THIN_DOWN_BOX, fl_thin_down_box, 1, 1, 2, 2); 00405 set_boxtype(_FL_ROUND_UP_BOX, fl_round_up_box, 3, 3, 6, 6); 00406 set_boxtype(_FL_ROUND_DOWN_BOX, fl_round_down_box, 3, 3, 6, 6); 00407 00408 // Use standard size scrollbars... 00409 Fl::scrollbar_size(16); 00410 } 00411 00412 // Set (or clear) the background tile for all windows... 00413 for (win = first_window(); win; win = next_window(win)) { 00414 win->labeltype(scheme_bg_ ? FL_NORMAL_LABEL : FL_NO_LABEL); 00415 win->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); 00416 win->image(scheme_bg_); 00417 win->redraw(); 00418 } 00419 00420 return 1; 00421 } 00422 00423 00424 // 00425 // End of "$Id: Fl_get_system_colors.cxx 7903 2010-11-28 21:06:39Z matt $". 00426 //