/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CThemes.cpp  -  description
                             -------------------
    begin                : Fri Nov 08 20003
    copyright            : (C) 2003-2005 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library is distributed in the hope that it will be useful, but 
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#include <FL/fl_draw.h>
#include <FL/Fl_XPM_Image.h>
#include <FL/Enumerations.h>
#include <sptk3/sptk-config.h>
#include <sptk3/CThemes.h>
#include <sptk3/CDirectoryDS.h>
#include <sptk3/string_ext.h>

#ifdef _WIN32   
#include <windows.h>
#endif

#include <stdio.h>

using namespace std;

extern void fl_internal_boxtype(Fl_Boxtype,Fl_Box_Draw_F*);

CThemes  themes;

Fl_Box_Draw_F *CThemes::m_flatBox;
Fl_Box_Draw_F *CThemes::m_thinUpBox;
Fl_Box_Draw_F *CThemes::m_upBox;
Fl_Box_Draw_F *CThemes::m_thinDownBox;
Fl_Box_Draw_F *CThemes::m_downBox;

Fl_Image      *CThemes::m_background[7];
Fl_Image      *CThemes::m_progressBar[2];
CScrollBarImages CThemes::m_scrollBar[2];
CButtonImage   CThemes::m_normalButtons[4];
CButtonImage   CThemes::m_comboButtons[4];
CButtonImage   CThemes::m_checkButtons[4];
CButtonImage   CThemes::m_radioButtons[4];
CButtonImage   CThemes::m_largeButtons[4];
bool           CThemes::m_flatButtons;

CRegistry     *CThemes::m_registry;
bool           CThemes::m_desaturateInactiveButtons;
int            CThemes::m_buttonFocusRadius;

CButtonImage::CButtonImage(Fl_Image *img) { 
   m_colorImage = m_grayImage = 0L; set(img,false);
}

void CButtonImage::clear() {
   if (m_colorImage) {
      delete m_colorImage;
      delete m_grayImage;
      m_colorImage = m_grayImage = 0L;
   }
}

CButtonImage::~CButtonImage() {
   clear();
}

void CButtonImage::set(Fl_Image *img,bool desaturateInactive) {
   clear();
   if (img) {
      m_colorImage = img;
      m_grayImage  = img->copy();
      if (desaturateInactive)
         m_grayImage->desaturate();
   }
}

static Fl_XPM_Image *loadValidateXPMImage(string fileName) {
   Fl_XPM_Image *img = new Fl_XPM_Image(fileName.c_str());
   if (img) {
      if (img->data()) return img;
      delete img;
      img = 0L;
   }
   return img;
}

void CScrollBarImages::load(int buttonSize,string themeDir,CThemeScrollBarType atype) {
   m_buttonSize = buttonSize;
   string scrollBarDir = themeDir+"/";
   if (atype == THM_SCROLLBAR_VERTICAL) 
      scrollBarDir += "vscrollbar";
   else
      scrollBarDir += "hscrollbar";
   clear();
   m_normalImage = loadValidateXPMImage(scrollBarDir+"0.xpm");
   m_activeImage = loadValidateXPMImage(scrollBarDir+"1.xpm");
   m_sliderImage = loadValidateXPMImage(scrollBarDir+"2.xpm");
}

void CScrollBarImages::clear() {
   if (m_normalImage) {
      delete m_normalImage;
      m_normalImage = 0L;
   }
   if (m_activeImage) {
      delete m_activeImage;
      m_activeImage = 0L;
   }
   if (m_sliderImage) {
      delete m_sliderImage;
      m_sliderImage = 0L;
   }
}

CThemes::CThemes() {
   m_flatBox = Fl::get_boxtype(FL_FLAT_BOX);
   m_thinUpBox = Fl::get_boxtype(FL_THIN_UP_BOX);
   m_upBox = Fl::get_boxtype(FL_UP_BOX);
   m_thinDownBox = Fl::get_boxtype(FL_THIN_DOWN_BOX);
   m_downBox = Fl::get_boxtype(FL_DOWN_BOX);

   m_registry = 0L;
   m_desaturateInactiveButtons = false;
   m_buttonFocusRadius = 0;

   unsigned i;
   for (i = 0; i < 7; i++) m_background[i] = 0L;
}

CThemes::~CThemes() {
   if (m_registry) delete m_registry;
}

string CThemes::directory() {
#ifdef _WIN32   
   char windir[128];
   GetWindowsDirectory(windir,128);
   return windir + string("\\.themes.sptk");
#else
   return string(THEMES_PREFIX) + "/share/sptk";
#endif
}

void CThemes::reset() {
   Fl::set_boxtype(FL_FLAT_BOX,m_flatBox,0,0,0,0);
   Fl::set_boxtype(FL_THIN_UP_BOX,m_thinUpBox,1,1,2,2);
   Fl::set_boxtype(FL_UP_BOX,m_upBox,2,2,4,4);
   Fl::set_boxtype(FL_THIN_DOWN_BOX,m_thinDownBox,1,1,2,2);
   Fl::set_boxtype(FL_DOWN_BOX,m_downBox,2,2,4,4);

   unsigned i = 0;
   for (; i < 4; i++) 
      m_normalButtons[i].clear();

   for (i = 0; i < 2; i++) {
      m_comboButtons[i].clear();
      m_radioButtons[i].clear();
      m_checkButtons[i].clear();
   }
   m_scrollBar[THM_SCROLLBAR_VERTICAL].clear();
   m_scrollBar[THM_SCROLLBAR_HORIZONTAL].clear();
}

CButtonImage *CThemes::sizeToButtonImages(CThemeButtonSize sz) {
   switch (sz) {
      case THM_BUTTON_COMBO:
         return m_comboButtons;
      case THM_BUTTON_CHECK:
         return m_checkButtons;
      case THM_BUTTON_RADIO:
         return m_radioButtons;
      case THM_BUTTON_LARGE:
         return m_largeButtons;
      case THM_BUTTON_NORMAL:
         break;
   }
   return m_normalButtons;
}

void CThemes::replaceButton(CThemeButtonSize sz,CThemeButtonType btndx,string fileName) {
   Fl_XPM_Image *img = loadValidateXPMImage(fileName);
   CButtonImage *buttons = sizeToButtonImages(sz);
   if (img)
      buttons[btndx].set(img,m_desaturateInactiveButtons);
   else
      buttons[btndx].clear();
}

void CThemes::replaceImage(Fl_Image *images[],int ndx,string fileName) {
   if (images[ndx]) 
      delete images[ndx]; 
   images[ndx] = loadValidateXPMImage(fileName);
}

void CThemes::set(string themeName) {
   reset();
   if (themeName == "" || themeName == "default")
      return;
#ifdef _WIN32   
   string slash = "\\";
   char windir[128];
   GetWindowsDirectory(windir,128);
   string dirname = directory() + slash + themeName;
#else
   string slash = "/";
   string dirname = directory() + slash + themeName;
#endif

   m_desaturateInactiveButtons = false;
   int scrollBarButtonSize = 0;
   try {
      if (m_registry) delete m_registry;
      m_registry = new CRegistry(dirname + slash + "theme.ini","",PROGRAM_REGISTRY);
      m_registry->load();
      m_registry->topic("Buttons");
      m_desaturateInactiveButtons = lowerCase((*m_registry)["Desaturate Inactive"]) == "true";
      m_buttonFocusRadius = (*m_registry)["Focus Radius"];
      m_flatButtons = lowerCase((*m_registry)["Flat Inactive"]) == "true";
   }
   catch (...) {
   }

   unsigned i;
   for (i = 0; i < 7; i++) 
      replaceImage(m_background,i,dirname + slash + "background"+int2string(i)+".xpm");

   for (i = 0; i < 2; i++) 
      replaceImage(m_progressBar,i,dirname + slash + "progress"+int2string(i)+".xpm");

   for (i = 0; i < 4; i++) 
      replaceButton(THM_BUTTON_NORMAL,CThemeButtonType(i),dirname + slash + "button"+int2string(i)+".xpm");

   for (i = 0; i < 2; i++) {
      replaceButton(THM_BUTTON_COMBO,CThemeButtonType(i),dirname + slash + "combo_button"+int2string(i)+".xpm");
      replaceButton(THM_BUTTON_CHECK,CThemeButtonType(i),dirname + slash + "check_button"+int2string(i)+".xpm");
      replaceButton(THM_BUTTON_RADIO,CThemeButtonType(i),dirname + slash + "radio_button"+int2string(i)+".xpm");
      replaceButton(THM_BUTTON_LARGE,CThemeButtonType(i),dirname + slash + "large_button"+int2string(i)+".xpm");
   }

   try {	
      m_registry->topic("Scrollbars");
      scrollBarButtonSize = (*m_registry)["Button Size"];
   }
   catch (...) {
   }

   m_scrollBar[THM_SCROLLBAR_VERTICAL].load(scrollBarButtonSize,dirname,THM_SCROLLBAR_VERTICAL);
   m_scrollBar[THM_SCROLLBAR_HORIZONTAL].load(scrollBarButtonSize,dirname,THM_SCROLLBAR_HORIZONTAL);

   Fl::set_boxtype(FL_FLAT_BOX,drawFlatBox,0,0,0,0);
   Fl::set_boxtype(FL_THIN_DOWN_BOX,drawThinDownBox,1,1,2,2);
   Fl::set_boxtype(FL_DOWN_BOX,drawDownBox,2,2,4,4);
   Fl::set_boxtype(FL_UP_BOX,drawUpBox,2,2,4,4);
   Fl::set_boxtype(FL_THIN_UP_BOX,drawThinUpBox,1,1,2,2);
}

Fl_Image *CThemes::imageForColor(Fl_Color clr) {
   if (clr >= FL_DARK3 && clr <= FL_LIGHT3) {
      int ndx = 0;
      switch (clr) {
         case FL_DARK3: ndx = 0; break;
         case FL_DARK2: ndx = 1; break;
         case FL_DARK1: ndx = 2; break;
         case FL_BACKGROUND_COLOR: ndx = 3; break;
         case FL_LIGHT1: ndx = 4; break;
         case FL_LIGHT2: ndx = 5; break;
         case FL_LIGHT3: ndx = 6; break;
         default: return 0;
      }
      return m_background[ndx];
   }
   return 0L;
}

void CThemes::paintBackground(int xx,int yy,int ww,int hh,Fl_Image *image) {
   if (!image) return;
   if (ww < 0 || hh < 0) return;
   int dx = image->w();
   int dy = image->h();
   fl_push_clip(xx,yy,ww,hh);
   int maxx = xx + ww;
   int maxy = yy + hh;
   /// Image alignments
   yy = (yy / dy) * dy;
   xx = (xx / dx) * dx;
   for (int xi = xx; xi < maxx; xi += dx) {
      for (int yi = yy; yi < maxy; yi += dy) {
         image->draw(xi,yi,dx,dy,0,0);
         //image->draw(xi,yi);
      }
   }
   fl_pop_clip();
}

void CThemes::drawFlatBox(int x,int y,int w,int h,Fl_Color clr) {
   Fl_Image *image = imageForColor(clr);
   if (image) {
      paintBackground(x,y,w,h,image);
   } else {
      fl_color(clr);
      fl_rectf(x,y,w,h);
   }
}

void CThemes::drawThinUpBox(int x,int y,int w,int h,Fl_Color clr) {
   Fl_Image *image = imageForColor(clr);
   if (image) {
      paintBackground(x,y,w,h,image);
   } else {
      fl_color(clr);
      fl_rectf(x,y,w,h);
   }
   fl_draw_box(FL_THIN_UP_FRAME,x,y,w,h,clr);
}

void CThemes::drawUpBox(int x,int y,int w,int h,Fl_Color clr) {
   Fl_Image *image = imageForColor(clr);
   if (image) {
      paintBackground(x,y,w,h,image);
   } else {
      fl_color(clr);
      fl_rectf(x,y,w,h);
   }
   fl_draw_box(FL_UP_FRAME,x,y,w,h,clr);
}

void CThemes::drawThinDownBox(int x,int y,int w,int h,Fl_Color clr) {
   Fl_Image *image = imageForColor(clr);
   if (image) {
      paintBackground(x,y,w,h,image);
   } else {
      fl_color(clr);
      fl_rectf(x,y,w,h);
   }
   fl_draw_box(FL_THIN_DOWN_FRAME,x,y,w,h,clr);
}

void CThemes::drawDownBox(int x,int y,int w,int h,Fl_Color clr) {
   Fl_Image *image = imageForColor(clr);
   if (image) {
      paintBackground(x,y,w,h,image);
   } else {
      fl_color(clr);
      fl_rectf(x,y,w,h);
   }
   fl_draw_box(FL_DOWN_FRAME,x,y,w,h,clr);
}

bool CThemes::sizeButton(CThemeButtonSize sz,int& w,int& h) {
   CButtonImage *buttons = sizeToButtonImages(sz);
   Fl_Image *image = buttons[0].m_colorImage;
   if (!image) return false;
   if (sz == THM_BUTTON_COMBO) {
      w = image->w();
   } else {
      if (w < image->h() + CThemes::m_buttonFocusRadius)
         w = image->h() + CThemes::m_buttonFocusRadius;
   }
   h = image->h();
   return true;
}

void CThemes::paintHorizStretchedImage(int x,int y,int w,int zone,Fl_Image *image,CRect *fragment) {
   int imageX = 0;
   int imageY = 0;

   int imageW = image->w();
   if (fragment && fragment->x()+fragment->w() < imageW) {
      imageX = fragment->x();
      imageW = fragment->w();
   }

   int imageH = image->h();
   if (fragment && fragment->y()+fragment->h() < imageH) {
      imageY = fragment->y();
      imageH = fragment->h();
   }

   int sideFrame = w / 2;
   if (w % 2) sideFrame++;

   if (imageW < sideFrame * 2) {
      sideFrame = imageW / 2 - 2;
      if (sideFrame < 0) sideFrame = 0;
   }
   if (zone > sideFrame) zone = sideFrame;

   // Draw the left edge
   image->draw(x,y,zone,imageH,imageX,imageY);

   // Draw the middle area
   int xstart = x + zone;
   int xend = x + w - zone;
   int xsize = imageW - 2 * zone;
   if (xsize > 0) {
      for (int xx = xstart; xx < xend; xx += xsize) {
         if (xx + xsize > xend) xsize = xend - xx;
         image->draw(xx,y,xsize,imageH,imageX+zone,imageY);
      }
   }

  // Draw the right edge
   image->draw(x+w-zone,y,zone,imageH,imageX+imageW-zone,imageY);
}

void CThemes::paintVertStretchedImage(int x,int y,int h,int zone,Fl_Image *image,CRect *fragment) {
   int imageX = 0;
   int imageY = 0;

   int imageW = image->w();
   int imageH = image->h();

   if (fragment && fragment->x()+fragment->w() < imageW) {
      imageX = fragment->x();
      imageW = fragment->w();
   }

   if (fragment && fragment->y()+fragment->h() < imageH) {
      imageY = fragment->y();
      imageH = fragment->h();
   }

   int sideFrame = h / 2;
   if (h % 2) sideFrame++;

   if (imageH < sideFrame * 2) {
      sideFrame = imageH / 2 - 2;
      if (sideFrame < 0) sideFrame = 0;
   }
   if (zone > sideFrame) zone = sideFrame;

   // Draw the top edge
   image->draw(x,y,imageW,zone,imageX,imageY);

   // Draw the middle area
   int ystart = y + zone;
   int yend = y + h - zone;
   int ysize = imageH - 2 * zone;
   if (ysize > 0) {
      for (int yy = ystart; yy < yend; yy += ysize) {
         if (yy + ysize > yend) ysize = yend - yy;
         image->draw(x,yy,imageW,ysize,imageX,imageY+zone);
      }
   }

  // Draw the bottom edge
   image->draw(x,y+h-zone,imageW,zone,imageX,imageY+imageH-zone);
}

bool CThemes::drawButton(CThemeButtonSize sz,int x,int y,int& w,int& h,bool highlited,bool pressed,bool defaultButton) {
   int ndx = 0;
   if (defaultButton) {
      x -= 2;
      y -= 2;
      ndx += 2;
   }

   if (pressed) ndx++;

   Fl_Image *image;
   CButtonImage *buttons = sizeToButtonImages(sz);
   if (highlited) 
      image = buttons[ndx].m_colorImage;
   else image = buttons[ndx].m_grayImage;

   if (!image || image->w() < 10) {
      return false;
   }

   h = image->h();

   if (m_flatButtons && !highlited) {
      if (defaultButton) {
         fl_draw_box(FL_DOWN_BOX,x,y,w,h,FL_BACKGROUND_COLOR);
      } else {
         fl_draw_box(FL_FLAT_BOX,x,y,w,h,FL_BACKGROUND_COLOR);
      }
   } else {
      paintHorizStretchedImage(x,y,w,10,image);
   }

   return true;
}

bool CThemes::drawCheckButton(int x,int y,bool checked,bool highlited) {
   Fl_Image *image;
   int ndx = 0;
   if (checked) ndx = 1;
   if (highlited) 
      image = m_checkButtons[ndx].m_colorImage;
   else image = m_checkButtons[ndx].m_grayImage;

   if (!image || image->w() < 10) return false;

   image->draw(x,y);

   return true;
}

bool CThemes::drawRadioButton(int x,int y,bool checked,bool highlited) {
   Fl_Image *image;
   int ndx = 0;
   if (checked) ndx = 1;
   if (highlited) 
      image = m_radioButtons[ndx].m_colorImage;
   else image = m_radioButtons[ndx].m_grayImage;

   if (!image || image->w() < 10) return false;

   image->draw(x,y);

   return true;
}

bool CThemes::sizeProgressBar(int& w,int& h) {
   Fl_Image *image = m_progressBar[0];
   if (image && image->data()) {
      w = image->w();
      h = image->h();
      return true;
   } else {
      w = h = 0;
      return false;
   }
}

bool CThemes::drawProgressBar(int x,int y,int w,float percent) {
   if (percent > 100) percent = 100;
   if (percent < 0) percent = 0;
   if (m_progressBar[0] && m_progressBar[0]->data()) {
      int xspace = (m_progressBar[0]->w() - m_progressBar[1]->w()) / 2; 
      int yspace = (m_progressBar[0]->h() - m_progressBar[1]->h()) / 2; 
      int psize  = int((w - xspace * 2) * percent / 100 + 0.5);
      paintHorizStretchedImage(x,y,w,10,m_progressBar[0]);
      paintHorizStretchedImage(x+xspace,y+yspace,psize,8,m_progressBar[1]);
      return true;
   } else {
      return false;
   }
}

bool CThemes::sizeScrollBar(int& w,int& h) {
   bool vertical = w < h;
   CScrollBarImages *images = &m_scrollBar[THM_SCROLLBAR_HORIZONTAL];
   if (vertical)
      images = &m_scrollBar[THM_SCROLLBAR_VERTICAL];
   if (images->m_normalImage) {
      if (vertical) {
         w = images->m_normalImage->w();
         if (h < images->buttonSize() * 2 + 10)
            h = images->buttonSize() * 2 + 10;
      } else {
         h = images->m_normalImage->h();
         if (w < images->buttonSize() * 2 + 10)
            w= images->buttonSize() * 2 + 10;
      }
      return true;
   }
   if (vertical) {
      w = 16;
      if (h < 44) h = 44;
   } else {
      h = 16;
      if (w < 44) w = 44;
   }
   return false;
}

bool CThemes::drawScrollBar(int x,int y,int w,int h,float minimum,float maximum,float value,float sliderSize,int activeZone,bool active) {
   bool vertical = w < h;

   // Selecting the group of images
   CScrollBarImages *images = &m_scrollBar[THM_SCROLLBAR_HORIZONTAL];
   if (vertical)
      images = &m_scrollBar[THM_SCROLLBAR_VERTICAL];

   // Painting the background
   int bsize = images->buttonSize();
   if (!bsize) bsize = 14;
   Fl_Image *normalImage = images->m_normalImage;
   Fl_Image *activeImage = images->m_activeImage;
   if (normalImage && activeImage) {
      if (vertical) {
         CRect backgroundRect(0,bsize,normalImage->w(),normalImage->h()-bsize*2-1); 
         paintVertStretchedImage(x,y+bsize,h-bsize*2,10,normalImage,&backgroundRect);
      } else {
         CRect backgroundRect(bsize,0,normalImage->w()-bsize*2-1,normalImage->h()); 
         paintHorizStretchedImage(x+bsize,y,w-bsize*2,10,normalImage,&backgroundRect);
      }
   } else {
      fl_draw_box(FL_THIN_DOWN_BOX,x,y,w,h,FL_DARK3);
   }

   // Painting the buttons
   Fl_Image *firstButtonSrc = normalImage;
   Fl_Image *secondButtonSrc = normalImage;
   switch (activeZone) {
      case 1: firstButtonSrc = activeImage; break;
      case 2: secondButtonSrc = activeImage; break;
   }

   if (normalImage) {
      // Images available
      if (vertical) {
         firstButtonSrc->draw(x,y,normalImage->w(),bsize,0,0);
         secondButtonSrc->draw(x,y+h-bsize,normalImage->w(),bsize,0,normalImage->h()-bsize-1);
      } else {
         firstButtonSrc->draw(x,y,bsize,normalImage->h(),0,0);
         secondButtonSrc->draw(x+w-bsize,y,bsize,normalImage->h(),normalImage->w()-bsize-1,0);
      }
   } else {
      // Images not available
      if (vertical) {
         fl_draw_box(activeZone==1?FL_FLAT_BOX:FL_THIN_UP_BOX,x+1,y+1,w-2,bsize,FL_BACKGROUND_COLOR);
         fl_draw_box(activeZone==2?FL_FLAT_BOX:FL_THIN_UP_BOX,x+1,y+h-bsize-1,w-2,bsize,FL_BACKGROUND_COLOR);
         if (active)
            fl_color(FL_BLACK);
         else
            fl_color(fl_inactive(FL_BLACK));
         int w1 = (w-4)/3; if (w1 < 1) w1 = 1;
         int x1 = x+(w-2*w1-1)/2;
         int yy1 = y+(w-w1-1)/2;
         fl_polygon(x1, yy1+w1, x1+2*w1, yy1+w1, x1+w1, yy1);
         yy1 += h-w;
         fl_polygon(x1, yy1, x1+w1, yy1+w1, x1+2*w1, yy1);
      } else {
         fl_draw_box(activeZone==1?FL_FLAT_BOX:FL_THIN_UP_BOX,x+1,y+1,bsize,h-2,FL_BACKGROUND_COLOR);
         fl_draw_box(activeZone==2?FL_FLAT_BOX:FL_THIN_UP_BOX,x+w-bsize-1,y+1,bsize,h-2,FL_BACKGROUND_COLOR);
         if (active)
            fl_color(FL_BLACK);
         else
            fl_color(fl_inactive(FL_BLACK));
         int w1 = (h-4)/3; if (w1 < 1) w1 = 1;
         int x1 = x+(h-w1-1)/2;
         int yy1 = y+(h-2*w1-1)/2;
         fl_polygon(x1, yy1+w1, x1+w1, yy1+2*w1, x1+w1, yy1);
         x1 += (w-h);
         fl_polygon(x1, yy1, x1, yy1+2*w1, x1+w1, yy1+w1);
      }
   }

   // Draw the slider
   double val;
   if (minimum == maximum)
      val = 0.5;
   else {
      val = (value-minimum)/(maximum-minimum);
      if (val > 1.0) val = 1.0;
      else if (val < 0.0) val = 0.0;
   }

   int ww = (vertical ? h : w) - bsize * 2;
   int S = int(sliderSize * ww+.5);
   if (S < 10) S = 10;
   int xx = int(val*(ww-S)+.5) + bsize;

   int xsl, ysl, wsl, hsl;
   Fl_Image *sliderImage = images->m_sliderImage;
   if (vertical) {
      ysl = y+xx;
      hsl = S;
      xsl = x;
      wsl = w;
      if (hsl > 0 && sliderImage) {
         int offset = (wsl - sliderImage->w()) / 2;
         paintVertStretchedImage(xsl+offset,ysl,hsl,10,sliderImage);
      }
   } else {
      xsl = x+xx;
      wsl = S;
      ysl = y;
      hsl = h;
      if (wsl > 0 && sliderImage) { 
         int offset = (hsl - sliderImage->h()) / 2;
         paintHorizStretchedImage(xsl,ysl+offset,wsl,10,sliderImage);
      }
   }
   if (!normalImage && wsl>0 && hsl>0) {
      fl_draw_box(FL_THIN_UP_BOX,xsl+1,ysl+1,wsl-2,hsl-2,FL_BACKGROUND_COLOR);
   }

   return true;
}

CStrings CThemes::availableThemes() {
   CStrings  themes;
   CDirectoryDS   dir;
   themes.push_back("Default");
   try {
      dir.directory(directory());
      dir.showPolicy(DDS_HIDE_FILES|DDS_HIDE_DOT_FILES);
      dir.open();
      while (!dir.eof()) {
         if (dir["Type"].asString() == "Directory") {
            std::string dirName = dir["Name"];
            if (dirName != "CVS")
               themes.push_back(dirName);
         }
         dir.next();
      }
   }
   catch (...) {
   }
   dir.close();

   return themes;
}
