1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-28 09:22:27 +01:00
Files
wmaker/WINGs/wcolorpanel.c
dan 36e46831e0 For libwraster:
---------------

- Added retain/release mechanism to RImage by adding RRetainImage() and
  RReleaseImage(). RDestroyImage() is an alias to RReleaseImage() now, but
  will be removed in a future release because it no longer fits with the
  semantics. Will be kept for a while to allow a smoother transition.
  More about in wrlib/NEWS


For WINGs:
----------

- Small API change:
  1. Renamed WMSetApplicationIconImage(), WMGetApplicationIconImage() and
     WMSetWindowMiniwindowImage() to respectively WMSetApplicationIconPixmap(),
     WMGetApplicationIconPixmap() and WMSetWindowMiniwindowPixmap()
     They operate on a WMPixmap which is practically an X Pixmap with no alpha
     channel information and the new name is more suggestive and also leaves
     room for the new functions added for operating on images with alpha info.
  2. Added WMSetApplicationIconImage() and WMGetApplicationIconImage() which
     operate on an RImage and store alpha information too.
  3. Added WMGetApplicationIconBlendedPixmap() which will take the image with
     alpha set by WMSetApplicationIconImage() and will blend it with a color.
     If color is NULL it will blend using the default panel color (#aeaaae)
  All these changes will allow WINGs to handle images with alpha blending
  correctly in panels and wherever else needed. More about in WINGs/NEWS.
- updated panels to use the newly available RImages if present and fallback
  to old WMPixmaps if not, to properly show alpha blended images.
- replaced some still left malloc's with wmalloc's.


For Window Maker:
-----------------
- Fixed wrong mapping position of the "Docked Applications Panel" for some
  icons.
- Smoother animation for the smiley =)
- Made images with alpha blending be shown correctly in the panels and the
  icon chooser.
- The icon image set to be shown in panels ("Logo.WMPanel") will be
  automatically updated if its entry in WMWindowAttributes changes (without
  a need to restart as until now).


*** Note!!! ***

If you are developing applications with one of libwraster or libWINGs
then you should look to wrlib/NEWS and WINGs/NEWS to see what changed
and how should you update your code.
2001-04-21 07:12:21 +00:00

3795 lines
112 KiB
C

/*
* ColorPanel for WINGs
*
* by ]d : Original idea and basic initial code
* Pascal Hofstee : Code for wheeldrawing and calculating
* colors from it.
* Primary coder of this Color Panel.
* Alban Hertroys : Optimizations for algorithms for color-
* wheel. Also custom ColorPalettes and
* magnifying glass. Secondary coder ;)
* Alfredo K. Kojima : For pointing out memory-allocation
* problems and similair code-issues
* Marco van Hylckama-Vlieg : For once again doing the artwork ;-)
*
*/
/* TODO:
* - Look at further optimization of colorWheel matrix calculation.
* It appears to be rather symmetric in angles of 60 degrees,
* while it is optimized in angles of 90 degrees.
* - Custom color-lists and custom colors in custom color-lists.
* - Stored colors
* - Resizing
*/
#include "../src/config.h"
#include "WINGsP.h"
#include <math.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
/* BUG There's something fishy with shaped windows */
#if 1
#ifdef SHAPE
#define SHAPE_WAS_DEFINED
#undef SHAPE
#endif
#endif
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#ifndef PATH_MAX
# define PATH_MAX 1024
#endif
char *WMColorPanelColorChangedNotification = "WMColorPanelColorChangedNotification";
/*
* Error Messages
*/
#define NO_MEMORY_ERR "Color Panel: Could not allocate memory"
#define NO_FILE_ERR "Color Panel: Could not find file"
#define X_ERR "Color Panel: X failed request"
/*
* Bitmaps for magnifying glass cursor
*/
/* Cursor */
#define Cursor_x_hot 11
#define Cursor_y_hot 11
#define Cursor_width 32
#define Cursor_height 32
static unsigned char Cursor_bits[] = {
0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
0x00,0x08,0x00,0x50,0x00,0x10,0x00,0x88,0x00,0x20,0x00,0x5c,0x01,0xc0,0x81,
0x3b,0x02,0x00,0x7e,0x70,0x05,0x00,0x00,0xe0,0x08,0x00,0x00,0xc0,0x15,0x00,
0x00,0x80,0x23,0x00,0x00,0x00,0x57,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x5c,
0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x70};
/* Cursor shape-mask */
#define Cursor_shape_width 32
#define Cursor_shape_height 32
static unsigned char Cursor_shape_bits[] = {
0x00,0x7e,0x00,0x00,0xc0,0x81,0x03,0x00,0x20,0x00,0x04,0x00,0x10,0x00,0x08,
0x00,0x08,0x00,0x10,0x00,0x04,0x00,0x20,0x00,0x02,0x00,0x40,0x00,0x02,0x00,
0x40,0x00,0x02,0x00,0x40,0x00,0x01,0x42,0x80,0x00,0x01,0x24,0x80,0x00,0x01,
0x00,0x80,0x00,0x01,0x00,0x80,0x00,0x01,0x24,0x80,0x00,0x01,0x42,0x80,0x00,
0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x02,0x00,0x40,0x00,0x04,0x00,0x20,
0x00,0x08,0x00,0x70,0x00,0x10,0x00,0xf8,0x00,0x20,0x00,0xfc,0x01,0xc0,0x81,
0xfb,0x03,0x00,0x7e,0xf0,0x07,0x00,0x00,0xe0,0x0f,0x00,0x00,0xc0,0x1f,0x00,
0x00,0x80,0x3f,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfc,
0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x70};
/* Clip-mask for magnified pixels */
#define Cursor_mask_width 24
#define Cursor_mask_height 24
static unsigned char Cursor_mask_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0xff, 0x07,
0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f,
0xfc, 0xff, 0x3f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfc, 0xff, 0x3f,
0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f,
0xe0, 0xff, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00};
typedef struct MovingView {
WMView *view; /* The view this is all about */
XImage *image; /* What's under the view */
XImage *dirtyRect; /* Storage of overlapped image area */
Pixmap magPix; /* Magnified part of pixmap */
RColor color; /* Color of a pixel in the image */
int x, y; /* Position of view */
} MovingView;
typedef struct CPColor {
RColor rgb; /* The RGB values of the color */
RHSVColor hsv; /* The HSV values of the color */
enum { /* Which one was last set ? */
cpNone,
cpRGB,
cpHSV
} set;
} CPColor;
typedef struct WheelMatrix {
unsigned int width, height; /* Size of the colorwheel */
unsigned char *data[3]; /* Wheel data (R,G,B) */
unsigned char values[256]; /* Precalculated values R,G & B = 0-255 */
} wheelMatrix;
typedef struct W_ColorPanel {
WMWindow *win;
WMFont *font8;
WMFont *font12;
void *clientData;
WMAction2 *action;
/* Common Stuff */
WMColorWell *colorWell;
WMButton *magnifyBtn;
WMButton *wheelBtn;
WMButton *slidersBtn;
WMButton *customPaletteBtn;
WMButton *colorListBtn;
/* Magnifying Glass */
MovingView *magnifyGlass;
/* ColorWheel Panel */
WMFrame *wheelFrm;
WMSlider *wheelBrightnessS;
WMView *wheelView;
/* Slider Panels */
WMFrame *slidersFrm;
WMFrame *seperatorFrm;
WMButton *grayBtn;
WMButton *rgbBtn;
WMButton *cmykBtn;
WMButton *hsbBtn;
/* Gray Scale Panel */
WMFrame *grayFrm;
WMLabel *grayMinL;
WMLabel *grayMaxL;
WMSlider *grayBrightnessS;
WMTextField *grayBrightnessT;
WMButton *grayPresetBtn[7];
/* RGB Panel */
WMFrame *rgbFrm;
WMLabel *rgbMinL;
WMLabel *rgbMaxL;
WMSlider *rgbRedS;
WMSlider *rgbGreenS;
WMSlider *rgbBlueS;
WMTextField *rgbRedT;
WMTextField *rgbGreenT;
WMTextField *rgbBlueT;
/* CMYK Panel */
WMFrame *cmykFrm;
WMLabel *cmykMinL;
WMLabel *cmykMaxL;
WMSlider *cmykCyanS;
WMSlider *cmykMagentaS;
WMSlider *cmykYellowS;
WMSlider *cmykBlackS;
WMTextField *cmykCyanT;
WMTextField *cmykMagentaT;
WMTextField *cmykYellowT;
WMTextField *cmykBlackT;
/* HSB Panel */
WMFrame *hsbFrm;
WMSlider *hsbHueS;
WMSlider *hsbSaturationS;
WMSlider *hsbBrightnessS;
WMTextField *hsbHueT;
WMTextField *hsbSaturationT;
WMTextField *hsbBrightnessT;
/* Custom Palette Panel*/
WMFrame *customPaletteFrm;
WMPopUpButton *customPaletteHistoryBtn;
WMFrame *customPaletteContentFrm;
WMPopUpButton *customPaletteMenuBtn;
WMView *customPaletteContentView;
/* Color List Panel */
WMFrame *colorListFrm;
WMPopUpButton *colorListHistoryBtn;
WMList *colorListContentLst;
WMPopUpButton *colorListColorMenuBtn;
WMPopUpButton *colorListListMenuBtn;
/* Look-Up Tables and Images */
wheelMatrix *wheelMtrx;
Pixmap wheelImg;
Pixmap selectionImg;
Pixmap selectionBackImg;
RImage *customPaletteImg;
char *lastBrowseDir;
/* Common Data Fields */
CPColor color; /* Current color */
WMColorPanelMode mode; /* Current color selection mode */
WMColorPanelMode slidersmode; /* Current color sel. mode sliders panel */
WMColorPanelMode lastChanged; /* Panel that last changed the color */
int colx, coly; /* (x,y) of sel.-marker in WheelMode */
int palx, paly; /* (x,y) of sel.-marker in
CustomPaletteMode */
double palXRatio, palYRatio; /* Ratios in x & y between
original and scaled
palettesize */
int currentPalette;
char *configurationPath;
struct {
unsigned int continuous:1;
unsigned int dragging:1;
} flags;
} W_ColorPanel;
enum {
CPmenuNewFromFile,
CPmenuRename,
CPmenuRemove,
CPmenuCopy,
CPmenuNewFromClipboard
} customPaletteMenuItem;
enum {
CLmenuAdd,
CLmenuRename,
CLmenuRemove
} colorListMenuItem;
#define PWIDTH 194
#define PHEIGHT 266
#define colorWheelSize 150
#define customPaletteWidth 182
#define customPaletteHeight 106
#define knobThickness 8
#define SPECTRUM_WIDTH 511
#define SPECTRUM_HEIGHT 360
#define COLORWHEEL_PART 1
#define CUSTOMPALETTE_PART 2
#define BUFSIZE 1024
#ifndef RGBTXT
#define RGBTXT "/usr/X11R6/lib/X11/rgb.txt"
#endif
#define MAX_LENGTH 1024
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static int fetchFile(char* toPath, char *imageSrcFile,
char *imageDestFileName);
char *generateNewFilename(char *curName);
void convertCPColor(CPColor *color);
RColor ulongToRColor(WMScreen *scr, unsigned long value);
unsigned char getShift(unsigned char value);
static void modeButtonCallback(WMWidget *w, void *data);
static int getPickerPart(W_ColorPanel *panel, int x, int y);
static void readConfiguration(W_ColorPanel *panel);
static void readXColors(W_ColorPanel *panel);
static void closeWindowCallback(WMWidget *w, void *data);
static Cursor magnifyGrabPointer(W_ColorPanel *panel);
static WMPoint magnifyInitialize(W_ColorPanel *panel);
static void magnifyPutCursor(WMWidget *w, void *data);
static Pixmap magnifyCreatePixmap(WMColorPanel *panel);
static void magnifyGetImageStored(W_ColorPanel *panel, int x1, int y1,
int x2, int y2);
static XImage* magnifyGetImage(WMScreen *scr, XImage *image, int x, int y,
int w, int h);
static wheelMatrix* wheelCreateMatrix(unsigned int width , unsigned int height);
static void wheelDestroyMatrix(wheelMatrix *matrix);
static void wheelInitMatrix(W_ColorPanel *panel);
static void wheelCalculateValues(W_ColorPanel *panel, int maxvalue);
static void wheelRender(W_ColorPanel *panel);
static Bool wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs);
static void wheelPaint(W_ColorPanel *panel);
static void wheelHandleEvents(XEvent *event, void *data);
static void wheelHandleActionEvents(XEvent *event, void *data);
static void wheelBrightnessSliderCallback(WMWidget *w, void *data);
static void wheelUpdateSelection(W_ColorPanel *panel);
static void wheelUndrawSelection(W_ColorPanel *panel);
static void wheelPositionSelection(W_ColorPanel *panel, int x, int y);
static void wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y);
static void wheelUpdateBrightnessGradientFromLocation (W_ColorPanel *panel);
static void wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor);
static void grayBrightnessSliderCallback(WMWidget *w, void *data);
static void grayPresetButtonCallback(WMWidget *w, void *data);
static void grayBrightnessTextFieldCallback(void *observerData,
WMNotification *notification);
static void rgbSliderCallback(WMWidget *w, void *data);
static void rgbTextFieldCallback(void *observerData,
WMNotification *notification);
static void cmykSliderCallback(WMWidget *w, void *data);
static void cmykTextFieldCallback(void *observerData,
WMNotification *notification);
static void hsbSliderCallback(WMWidget *w, void *data);
static void hsbTextFieldCallback(void *observerData,
WMNotification *notification);
static void hsbUpdateBrightnessGradient(W_ColorPanel *panel);
static void hsbUpdateSaturationGradient(W_ColorPanel *panel);
static void hsbUpdateHueGradient(W_ColorPanel *panel);
static void customRenderSpectrum(W_ColorPanel *panel);
static void customSetPalette(W_ColorPanel *panel);
static void customPaletteHandleEvents(XEvent *event, void *data);
static void customPaletteHandleActionEvents(XEvent *event, void *data);
static void customPalettePositionSelection(W_ColorPanel *panel, int x, int y);
static void customPalettePositionSelectionOutBounds(W_ColorPanel *panel,
int x, int y);
static void customPaletteMenuCallback(WMWidget *w, void *data);
static void customPaletteHistoryCallback(WMWidget *w, void *data);
static void customPaletteMenuNewFromFile(W_ColorPanel *panel);
static void customPaletteMenuRename(W_ColorPanel *panel);
static void customPaletteMenuRemove(W_ColorPanel *panel);
static void colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
int state, WMRect *rect);
static void colorListSelect(WMWidget *w, void *data);
static void colorListColorMenuCallback(WMWidget *w, void *data);
static void colorListListMenuCallback(WMWidget *w, void *data);
static void colorListListMenuNew(W_ColorPanel *panel);
static void wheelInit(W_ColorPanel *panel);
static void grayInit(W_ColorPanel *panel);
static void rgbInit(W_ColorPanel *panel);
static void cmykInit(W_ColorPanel *panel);
static void hsbInit(W_ColorPanel *panel);
void
WMSetColorPanelAction(WMColorPanel *panel, WMAction2 *action, void *data)
{
panel->action = action;
panel->clientData = data;
}
static WMColorPanel*
makeColorPanel(WMScreen *scrPtr, char *name)
{
WMColorPanel *panel;
RImage *image;
WMPixmap *pixmap;
RColor from;
RColor to;
WMColor *textcolor, *graybuttoncolor;
int i;
GC bgc = WMColorGC(scrPtr->black);
GC wgc = WMColorGC(scrPtr->white);
panel = wmalloc(sizeof(WMColorPanel));
memset(panel, 0, sizeof(WMColorPanel));
panel->color.rgb.red = 0;
panel->color.rgb.green = 0;
panel->color.rgb.blue = 0;
panel->color.hsv.hue = 0;
panel->color.hsv.saturation = 0;
panel->color.hsv.value = 0;
panel->color.set = cpNone; /* Color has not been set yet */
panel->font8 = WMSystemFontOfSize(scrPtr, 8);
panel->font12 = WMSystemFontOfSize(scrPtr, 12);
panel->win = WMCreateWindowWithStyle(scrPtr, name,
WMTitledWindowMask | WMClosableWindowMask | WMResizableWindowMask);
WMResizeWidget(panel->win, PWIDTH, PHEIGHT);
WMSetWindowTitle(panel->win, "Colors");
WMSetWindowCloseAction(panel->win, closeWindowCallback, panel);
/* Set Default ColorPanel Mode(s) */
panel->mode = WMWheelModeColorPanel;
panel->lastChanged = 0;
panel->slidersmode = WMRGBModeColorPanel;
panel->configurationPath = wstrconcat(wusergnusteppath(),
"/Library/Colors/");
/* Some General Purpose Widgets */
panel->colorWell = WMCreateColorWell(panel->win);
WMResizeWidget(panel->colorWell, 134, 36);
WSetColorWellBordered(panel->colorWell, False);
WMMoveWidget(panel->colorWell, 56, 4);
panel->magnifyBtn = WMCreateCustomButton(panel->win,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->magnifyBtn, 46, 36);
WMMoveWidget(panel->magnifyBtn, 6,4);
WMSetButtonAction(panel->magnifyBtn, magnifyPutCursor, panel);
WMSetButtonImagePosition(panel->magnifyBtn, WIPImageOnly);
WMSetButtonImage(panel->magnifyBtn, scrPtr->magnifyIcon);
panel->wheelBtn = WMCreateCustomButton(panel->win,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->wheelBtn, 46, 32);
WMMoveWidget(panel->wheelBtn, 6, 44);
WMSetButtonAction(panel->wheelBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->wheelBtn, WIPImageOnly);
WMSetButtonImage(panel->wheelBtn, scrPtr->wheelIcon);
panel->slidersBtn = WMCreateCustomButton(panel->win,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->slidersBtn, 46, 32);
WMMoveWidget(panel->slidersBtn, 52, 44);
WMSetButtonAction(panel->slidersBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->slidersBtn, WIPImageOnly);
WMSetButtonImage(panel->slidersBtn, scrPtr->rgbIcon);
panel->customPaletteBtn = WMCreateCustomButton(panel->win,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->customPaletteBtn, 46, 32);
WMMoveWidget(panel->customPaletteBtn, 98, 44);
WMSetButtonAction(panel->customPaletteBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->customPaletteBtn, WIPImageOnly);
WMSetButtonImage(panel->customPaletteBtn, scrPtr->customPaletteIcon);
panel->colorListBtn = WMCreateCustomButton(panel->win,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->colorListBtn, 46, 32);
WMMoveWidget(panel->colorListBtn, 144, 44);
WMSetButtonAction(panel->colorListBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->colorListBtn, WIPImageOnly);
WMSetButtonImage(panel->colorListBtn, scrPtr->colorListIcon);
/* Let's Group some of them together */
WMGroupButtons(panel->wheelBtn, panel->slidersBtn);
WMGroupButtons(panel->wheelBtn, panel->customPaletteBtn);
WMGroupButtons(panel->wheelBtn, panel->colorListBtn);
/* Widgets for the ColorWheel Panel */
panel->wheelFrm = WMCreateFrame(panel->win);
WMSetFrameRelief(panel->wheelFrm, WRFlat);
WMResizeWidget(panel->wheelFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
WMMoveWidget(panel->wheelFrm, 5, 80);
panel->wheelView = W_CreateView(W_VIEW(panel->wheelFrm));
/* XXX Can we create a view ? */
W_ResizeView(panel->wheelView, colorWheelSize+4, colorWheelSize+4);
W_MoveView(panel->wheelView, 0, 0);
/* Create an event handler to handle expose/click events in ColorWheel */
WMCreateEventHandler(panel->wheelView,
ButtonPressMask|ButtonReleaseMask|EnterWindowMask|
LeaveWindowMask|ButtonMotionMask, wheelHandleActionEvents, panel);
WMCreateEventHandler(panel->wheelView, ExposureMask, wheelHandleEvents,
panel);
panel->wheelBrightnessS = WMCreateSlider(panel->wheelFrm);
WMResizeWidget(panel->wheelBrightnessS, 16, 153);
WMMoveWidget(panel->wheelBrightnessS, 5+colorWheelSize+14, 1);
WMSetSliderMinValue(panel->wheelBrightnessS, 0);
WMSetSliderMaxValue(panel->wheelBrightnessS, 255);
WMSetSliderAction(panel->wheelBrightnessS, wheelBrightnessSliderCallback,
panel);
WMSetSliderKnobThickness(panel->wheelBrightnessS, knobThickness);
panel->wheelMtrx = wheelCreateMatrix(colorWheelSize+4, colorWheelSize+4);
wheelInitMatrix(panel);
/* Widgets for the Slider Panels */
panel->slidersFrm = WMCreateFrame(panel->win);
WMSetFrameRelief(panel->slidersFrm, WRFlat);
WMResizeWidget(panel->slidersFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
WMMoveWidget(panel->slidersFrm, 4, 80);
panel->seperatorFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->seperatorFrm, WRPushed);
WMResizeWidget(panel->seperatorFrm, PWIDTH - 8, 2);
WMMoveWidget(panel->seperatorFrm, 0, 1);
panel->grayBtn = WMCreateCustomButton(panel->slidersFrm,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->grayBtn, 46, 24);
WMMoveWidget(panel->grayBtn, 1, 8);
WMSetButtonAction(panel->grayBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->grayBtn, WIPImageOnly);
WMSetButtonImage(panel->grayBtn, scrPtr->grayIcon);
panel->rgbBtn = WMCreateCustomButton(panel->slidersFrm,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->rgbBtn, 46, 24);
WMMoveWidget(panel->rgbBtn, 47, 8);
WMSetButtonAction(panel->rgbBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->rgbBtn, WIPImageOnly);
WMSetButtonImage(panel->rgbBtn, scrPtr->rgbIcon);
panel->cmykBtn = WMCreateCustomButton(panel->slidersFrm,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->cmykBtn, 46, 24);
WMMoveWidget(panel->cmykBtn, 93, 8);
WMSetButtonAction(panel->cmykBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->cmykBtn, WIPImageOnly);
WMSetButtonImage(panel->cmykBtn, scrPtr->cmykIcon);
panel->hsbBtn = WMCreateCustomButton(panel->slidersFrm,
WBBStateLightMask|WBBStateChangeMask);
WMResizeWidget(panel->hsbBtn, 46, 24);
WMMoveWidget(panel->hsbBtn, 139, 8);
WMSetButtonAction(panel->hsbBtn, modeButtonCallback, panel);
WMSetButtonImagePosition(panel->hsbBtn, WIPImageOnly);
WMSetButtonImage(panel->hsbBtn, scrPtr->hsbIcon);
/* Let's Group the Slider Panel Buttons Together */
WMGroupButtons(panel->grayBtn, panel->rgbBtn);
WMGroupButtons(panel->grayBtn, panel->cmykBtn);
WMGroupButtons(panel->grayBtn, panel->hsbBtn);
textcolor = WMDarkGrayColor(scrPtr);
/* Widgets for GrayScale Panel */
panel->grayFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->grayFrm, WRFlat);
WMResizeWidget(panel->grayFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
WMMoveWidget(panel->grayFrm, 0, 34);
panel->grayMinL = WMCreateLabel(panel->grayFrm);
WMResizeWidget(panel->grayMinL, 20, 10);
WMMoveWidget(panel->grayMinL, 2, 2);
WMSetLabelText(panel->grayMinL, "0");
WMSetLabelTextAlignment(panel->grayMinL, WALeft);
WMSetLabelTextColor(panel->grayMinL, textcolor);
WMSetLabelFont(panel->grayMinL, panel->font8);
panel->grayMaxL = WMCreateLabel(panel->grayFrm);
WMResizeWidget(panel->grayMaxL, 40, 10);
WMMoveWidget(panel->grayMaxL, 104, 2);
WMSetLabelText(panel->grayMaxL, "100");
WMSetLabelTextAlignment(panel->grayMaxL, WARight);
WMSetLabelTextColor(panel->grayMaxL, textcolor);
WMSetLabelFont(panel->grayMaxL, panel->font8);
panel->grayBrightnessS = WMCreateSlider(panel->grayFrm);
WMResizeWidget(panel->grayBrightnessS, 141, 16);
WMMoveWidget(panel->grayBrightnessS, 2, 14);
WMSetSliderMinValue(panel->grayBrightnessS, 0);
WMSetSliderMaxValue(panel->grayBrightnessS, 100);
WMSetSliderKnobThickness(panel->grayBrightnessS, knobThickness);
WMSetSliderAction(panel->grayBrightnessS, grayBrightnessSliderCallback,
panel);
from.red = 0;
from.green = 0;
from.blue = 0;
to.red = 255;
to.green = 255;
to.blue = 255;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->grayBrightnessS), pixmap->pixmap,
panel->font12, 2, 0, 100, WALeft, WMColorGC(scrPtr->white),
False, "Brightness", strlen("Brightness"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->grayBrightnessS, pixmap);
WMReleasePixmap(pixmap);
panel->grayBrightnessT = WMCreateTextField(panel->grayFrm);
WMResizeWidget(panel->grayBrightnessT, 40, 18);
WMMoveWidget(panel->grayBrightnessT, 146, 13);
WMSetTextFieldAlignment(panel->grayBrightnessT, WALeft);
WMAddNotificationObserver(grayBrightnessTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->grayBrightnessT);
for (i=0; i < 7; i++) {
pixmap = WMCreatePixmap(scrPtr, 13, 13, scrPtr->depth, False);
graybuttoncolor = WMCreateRGBColor(scrPtr, (255/6)*i << 8,
(255/6)*i << 8, (255/6)*i << 8, True);
WMPaintColorSwatch(graybuttoncolor, pixmap->pixmap, 0, 0, 15, 15);
WMReleaseColor(graybuttoncolor);
panel->grayPresetBtn[i] = WMCreateCommandButton(panel->grayFrm);
WMResizeWidget(panel->grayPresetBtn[i], 20, 24);
WMMoveWidget(panel->grayPresetBtn[i], 2+(i*20), 34);
WMSetButtonAction(panel->grayPresetBtn[i],
grayPresetButtonCallback, panel);
WMSetButtonImage(panel->grayPresetBtn[i], pixmap);
WMSetButtonImagePosition(panel->grayPresetBtn[i], WIPImageOnly);
WMReleasePixmap(pixmap);
}
/* End of GrayScale Panel */
/* Widgets for RGB Panel */
panel->rgbFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->rgbFrm, WRFlat);
WMResizeWidget(panel->rgbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
WMMoveWidget(panel->rgbFrm, 0, 34);
panel->rgbMinL = WMCreateLabel(panel->rgbFrm);
WMResizeWidget(panel->rgbMinL, 20, 10);
WMMoveWidget(panel->rgbMinL, 2, 2);
WMSetLabelText(panel->rgbMinL, "0");
WMSetLabelTextAlignment(panel->rgbMinL, WALeft);
WMSetLabelTextColor(panel->rgbMinL, textcolor);
WMSetLabelFont(panel->rgbMinL, panel->font8);
panel->rgbMaxL = WMCreateLabel(panel->rgbFrm);
WMResizeWidget(panel->rgbMaxL, 40, 10);
WMMoveWidget(panel->rgbMaxL, 104, 2);
WMSetLabelText(panel->rgbMaxL, "255");
WMSetLabelTextAlignment(panel->rgbMaxL, WARight);
WMSetLabelTextColor(panel->rgbMaxL, textcolor);
WMSetLabelFont(panel->rgbMaxL, panel->font8);
panel->rgbRedS = WMCreateSlider(panel->rgbFrm);
WMResizeWidget(panel->rgbRedS, 141, 16);
WMMoveWidget(panel->rgbRedS, 2, 14);
WMSetSliderMinValue(panel->rgbRedS, 0);
WMSetSliderMaxValue(panel->rgbRedS, 255);
WMSetSliderKnobThickness(panel->rgbRedS, knobThickness);
WMSetSliderAction(panel->rgbRedS, rgbSliderCallback, panel);
to.red = 255;
to.green = 0;
to.blue = 0;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->rgbRedS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Red",
strlen("Red"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->rgbRedS, pixmap);
WMReleasePixmap(pixmap);
panel->rgbRedT = WMCreateTextField(panel->rgbFrm);
WMResizeWidget(panel->rgbRedT, 40, 18);
WMMoveWidget(panel->rgbRedT, 146, 13);
WMSetTextFieldAlignment(panel->rgbRedT, WALeft);
WMAddNotificationObserver(rgbTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->rgbRedT);
panel->rgbGreenS = WMCreateSlider(panel->rgbFrm);
WMResizeWidget(panel->rgbGreenS, 141, 16);
WMMoveWidget(panel->rgbGreenS, 2, 36);
WMSetSliderMinValue(panel->rgbGreenS, 0);
WMSetSliderMaxValue(panel->rgbGreenS, 255);
WMSetSliderKnobThickness(panel->rgbGreenS, knobThickness);
WMSetSliderAction(panel->rgbGreenS, rgbSliderCallback, panel);
to.red = 0;
to.green = 255;
to.blue = 0;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->rgbGreenS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Green",
strlen("Green"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->rgbGreenS, pixmap);
WMReleasePixmap(pixmap);
panel->rgbGreenT = WMCreateTextField(panel->rgbFrm);
WMResizeWidget(panel->rgbGreenT, 40, 18);
WMMoveWidget(panel->rgbGreenT, 146, 35);
WMSetTextFieldAlignment(panel->rgbGreenT, WALeft);
WMAddNotificationObserver(rgbTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->rgbGreenT);
panel->rgbBlueS = WMCreateSlider(panel->rgbFrm);
WMResizeWidget(panel->rgbBlueS, 141, 16);
WMMoveWidget(panel->rgbBlueS, 2, 58);
WMSetSliderMinValue(panel->rgbBlueS, 0);
WMSetSliderMaxValue(panel->rgbBlueS, 255);
WMSetSliderKnobThickness(panel->rgbBlueS, knobThickness);
WMSetSliderAction(panel->rgbBlueS, rgbSliderCallback, panel);
to.red = 0;
to.green = 0;
to.blue = 255;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->rgbBlueS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, WMColorGC(scrPtr->white), False, "Blue",
strlen("Blue"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->rgbBlueS, pixmap);
WMReleasePixmap(pixmap);
panel->rgbBlueT = WMCreateTextField(panel->rgbFrm);
WMResizeWidget(panel->rgbBlueT, 40, 18);
WMMoveWidget(panel->rgbBlueT, 146, 57);
WMSetTextFieldAlignment(panel->rgbBlueT, WALeft);
WMAddNotificationObserver(rgbTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->rgbBlueT);
/* End of RGB Panel */
/* Widgets for CMYK Panel */
panel->cmykFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->cmykFrm, WRFlat);
WMResizeWidget(panel->cmykFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
WMMoveWidget(panel->cmykFrm, 0, 34);
panel->cmykMinL = WMCreateLabel(panel->cmykFrm);
WMResizeWidget(panel->cmykMinL, 20, 10);
WMMoveWidget(panel->cmykMinL, 2, 2);
WMSetLabelText(panel->cmykMinL, "0");
WMSetLabelTextAlignment(panel->cmykMinL, WALeft);
WMSetLabelTextColor(panel->cmykMinL, textcolor);
WMSetLabelFont(panel->cmykMinL, panel->font8);
panel->cmykMaxL = WMCreateLabel(panel->cmykFrm);
WMResizeWidget(panel->cmykMaxL, 40, 10);
WMMoveWidget(panel->cmykMaxL, 104, 2);
WMSetLabelText(panel->cmykMaxL, "100");
WMSetLabelTextAlignment(panel->cmykMaxL, WARight);
WMSetLabelTextColor(panel->cmykMaxL, textcolor);
WMSetLabelFont(panel->cmykMaxL, panel->font8);
panel->cmykCyanS = WMCreateSlider(panel->cmykFrm);
WMResizeWidget(panel->cmykCyanS, 141, 16);
WMMoveWidget(panel->cmykCyanS, 2, 14);
WMSetSliderMinValue(panel->cmykCyanS, 0);
WMSetSliderMaxValue(panel->cmykCyanS, 100);
WMSetSliderKnobThickness(panel->cmykCyanS, knobThickness);
WMSetSliderAction(panel->cmykCyanS, cmykSliderCallback, panel);
from.red = 255;
from.green = 255;
from.blue = 255;
to.red = 0;
to.green = 255;
to.blue = 255;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->cmykCyanS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Cyan",
strlen("Cyan"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->cmykCyanS, pixmap);
WMReleasePixmap(pixmap);
panel->cmykCyanT = WMCreateTextField(panel->cmykFrm);
WMResizeWidget(panel->cmykCyanT, 40, 18);
WMMoveWidget(panel->cmykCyanT, 146, 13);
WMSetTextFieldAlignment(panel->cmykCyanT, WALeft);
WMAddNotificationObserver(cmykTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->cmykCyanT);
panel->cmykMagentaS = WMCreateSlider(panel->cmykFrm);
WMResizeWidget(panel->cmykMagentaS, 141, 16);
WMMoveWidget(panel->cmykMagentaS, 2, 36);
WMSetSliderMinValue(panel->cmykMagentaS, 0);
WMSetSliderMaxValue(panel->cmykMagentaS, 100);
WMSetSliderKnobThickness(panel->cmykMagentaS, knobThickness);
WMSetSliderAction(panel->cmykMagentaS, cmykSliderCallback, panel);
to.red = 255;
to.green = 0;
to.blue = 255;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->cmykMagentaS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Magenta",
strlen("Magenta"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->cmykMagentaS, pixmap);
WMReleasePixmap(pixmap);
panel->cmykMagentaT = WMCreateTextField(panel->cmykFrm);
WMResizeWidget(panel->cmykMagentaT, 40, 18);
WMMoveWidget(panel->cmykMagentaT, 146, 35);
WMSetTextFieldAlignment(panel->cmykMagentaT, WALeft);
WMAddNotificationObserver(cmykTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->cmykMagentaT);
panel->cmykYellowS = WMCreateSlider(panel->cmykFrm);
WMResizeWidget(panel->cmykYellowS, 141, 16);
WMMoveWidget(panel->cmykYellowS, 2, 58);
WMSetSliderMinValue(panel->cmykYellowS, 0);
WMSetSliderMaxValue(panel->cmykYellowS, 100);
WMSetSliderKnobThickness(panel->cmykYellowS, knobThickness);
WMSetSliderAction(panel->cmykYellowS, cmykSliderCallback, panel);
to.red = 255;
to.green = 255;
to.blue = 0;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->cmykYellowS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Yellow",
strlen("Yellow"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->cmykYellowS, pixmap);
WMReleasePixmap(pixmap);
panel->cmykYellowT = WMCreateTextField(panel->cmykFrm);
WMResizeWidget(panel->cmykYellowT, 40, 18);
WMMoveWidget(panel->cmykYellowT, 146, 57);
WMSetTextFieldAlignment(panel->cmykYellowT, WALeft);
WMAddNotificationObserver(cmykTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->cmykYellowT);
panel->cmykBlackS = WMCreateSlider(panel->cmykFrm);
WMResizeWidget(panel->cmykBlackS, 141, 16);
WMMoveWidget(panel->cmykBlackS, 2, 80);
WMSetSliderMinValue(panel->cmykBlackS, 0);
WMSetSliderMaxValue(panel->cmykBlackS, 100);
WMSetSliderValue(panel->cmykBlackS, 0);
WMSetSliderKnobThickness(panel->cmykBlackS, knobThickness);
WMSetSliderAction(panel->cmykBlackS, cmykSliderCallback, panel);
to.red = 0;
to.green = 0;
to.blue = 0;
image = RRenderGradient(141, 16, &from, &to, RGRD_HORIZONTAL);
pixmap = WMCreatePixmapFromRImage(scrPtr, image, 0);
RReleaseImage(image);
if (pixmap)
W_PaintText(W_VIEW(panel->cmykBlackS), pixmap->pixmap, panel->font12,
2, 0, 100, WALeft, WMColorGC(scrPtr->black), False, "Black",
strlen("Black"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->cmykBlackS, pixmap);
WMReleasePixmap(pixmap);
panel->cmykBlackT = WMCreateTextField(panel->cmykFrm);
WMResizeWidget(panel->cmykBlackT, 40, 18);
WMMoveWidget(panel->cmykBlackT, 146, 79);
WMSetTextFieldAlignment(panel->cmykBlackT, WALeft);
WMAddNotificationObserver(cmykTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->cmykBlackT);
/* End of CMYK Panel */
/* Widgets for HSB Panel */
panel->hsbFrm = WMCreateFrame(panel->slidersFrm);
WMSetFrameRelief(panel->hsbFrm, WRFlat);
WMResizeWidget(panel->hsbFrm, PWIDTH - 8, PHEIGHT - 80 - 26 - 32);
WMMoveWidget(panel->hsbFrm, 0, 34);
panel->hsbHueS = WMCreateSlider(panel->hsbFrm);
WMResizeWidget(panel->hsbHueS, 141, 16);
WMMoveWidget(panel->hsbHueS, 2, 14);
WMSetSliderMinValue(panel->hsbHueS, 0);
WMSetSliderMaxValue(panel->hsbHueS, 359);
WMSetSliderKnobThickness(panel->hsbHueS, knobThickness);
WMSetSliderAction(panel->hsbHueS, hsbSliderCallback, panel);
panel->hsbHueT = WMCreateTextField(panel->hsbFrm);
WMResizeWidget(panel->hsbHueT, 40, 18);
WMMoveWidget(panel->hsbHueT, 146, 13);
WMSetTextFieldAlignment(panel->hsbHueT, WALeft);
WMAddNotificationObserver(hsbTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->hsbHueT);
panel->hsbSaturationS = WMCreateSlider(panel->hsbFrm);
WMResizeWidget(panel->hsbSaturationS, 141, 16);
WMMoveWidget(panel->hsbSaturationS, 2, 36);
WMSetSliderMinValue(panel->hsbSaturationS, 0);
WMSetSliderMaxValue(panel->hsbSaturationS, 100);
WMSetSliderKnobThickness(panel->hsbSaturationS, knobThickness);
WMSetSliderAction(panel->hsbSaturationS, hsbSliderCallback, panel);
panel->hsbSaturationT = WMCreateTextField(panel->hsbFrm);
WMResizeWidget(panel->hsbSaturationT, 40, 18);
WMMoveWidget(panel->hsbSaturationT, 146, 35);
WMSetTextFieldAlignment(panel->hsbSaturationT, WALeft);
WMAddNotificationObserver(hsbTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->hsbSaturationT);
panel->hsbBrightnessS = WMCreateSlider(panel->hsbFrm);
WMResizeWidget(panel->hsbBrightnessS, 141, 16);
WMMoveWidget(panel->hsbBrightnessS, 2, 58);
WMSetSliderMinValue(panel->hsbBrightnessS, 0);
WMSetSliderMaxValue(panel->hsbBrightnessS, 100);
WMSetSliderKnobThickness(panel->hsbBrightnessS, knobThickness);
WMSetSliderAction(panel->hsbBrightnessS, hsbSliderCallback, panel);
panel->hsbBrightnessT = WMCreateTextField(panel->hsbFrm);
WMResizeWidget(panel->hsbBrightnessT, 40, 18);
WMMoveWidget(panel->hsbBrightnessT, 146, 57);
WMSetTextFieldAlignment(panel->hsbBrightnessT, WALeft);
WMAddNotificationObserver(hsbTextFieldCallback, panel,
WMTextDidEndEditingNotification, panel->hsbBrightnessT);
/* End of HSB Panel */
WMReleaseColor(textcolor);
/* Widgets for the CustomPalette Panel */
panel->customPaletteFrm = WMCreateFrame(panel->win);
WMSetFrameRelief(panel->customPaletteFrm, WRFlat);
WMResizeWidget(panel->customPaletteFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
WMMoveWidget(panel->customPaletteFrm, 5, 80);
panel->customPaletteHistoryBtn = WMCreatePopUpButton(
panel->customPaletteFrm);
WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, "Spectrum");
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
WMGetPopUpButtonNumberOfItems(panel->customPaletteHistoryBtn)-1);
WMSetPopUpButtonAction(panel->customPaletteHistoryBtn,
customPaletteHistoryCallback, panel);
WMResizeWidget(panel->customPaletteHistoryBtn, PWIDTH - 8, 20);
WMMoveWidget(panel->customPaletteHistoryBtn, 0, 0);
panel->customPaletteContentFrm = WMCreateFrame(panel->customPaletteFrm);
WMSetFrameRelief(panel->customPaletteContentFrm, WRSunken);
WMResizeWidget(panel->customPaletteContentFrm, PWIDTH - 8, PHEIGHT - 156);
WMMoveWidget(panel->customPaletteContentFrm, 0, 23);
panel->customPaletteContentView = W_CreateView(
W_VIEW(panel->customPaletteContentFrm));
/* XXX Test if we can create a view */
W_ResizeView(panel->customPaletteContentView, customPaletteWidth,
customPaletteHeight);
W_MoveView(panel->customPaletteContentView, 2, 2);
/* Create event handler to handle expose/click events in CustomPalette */
WMCreateEventHandler(panel->customPaletteContentView,
ButtonPressMask|ButtonReleaseMask|EnterWindowMask| LeaveWindowMask |
ButtonMotionMask, customPaletteHandleActionEvents, panel);
WMCreateEventHandler(panel->customPaletteContentView, ExposureMask,
customPaletteHandleEvents, panel);
panel->customPaletteMenuBtn = WMCreatePopUpButton(panel->customPaletteFrm);
WMSetPopUpButtonPullsDown(panel->customPaletteMenuBtn, 1);
WMSetPopUpButtonText(panel->customPaletteMenuBtn, "Palette");
WMSetPopUpButtonAction(panel->customPaletteMenuBtn,
customPaletteMenuCallback, panel);
WMResizeWidget(panel->customPaletteMenuBtn, PWIDTH - 8, 20);
WMMoveWidget(panel->customPaletteMenuBtn, 0, PHEIGHT - 130);
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from File...");
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Rename...");
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Remove");
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "Copy");
WMAddPopUpButtonItem(panel->customPaletteMenuBtn, "New from Clipboard");
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename, 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove, 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuCopy, 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn,
CPmenuNewFromClipboard, 0);
customRenderSpectrum(panel);
panel->currentPalette = 0;
panel->palx = customPaletteWidth/2;
panel->paly = customPaletteHeight/2;
/* Widgets for the ColorList Panel */
panel->colorListFrm = WMCreateFrame(panel->win);
WMSetFrameRelief(panel->colorListFrm, WRFlat);
WMResizeWidget(panel->colorListFrm, PWIDTH - 8, PHEIGHT - 80 - 26);
WMMoveWidget(panel->colorListFrm, 5, 80);
panel->colorListHistoryBtn = WMCreatePopUpButton(panel->colorListFrm);
WMAddPopUpButtonItem(panel->colorListHistoryBtn, "X11-Colors");
WMSetPopUpButtonSelectedItem(panel->colorListHistoryBtn,
WMGetPopUpButtonNumberOfItems(panel->colorListHistoryBtn)-1);
/* WMSetPopUpButtonAction(panel->colorListHistoryBtn,
* colorListHistoryCallback, panel); */
WMResizeWidget(panel->colorListHistoryBtn, PWIDTH - 8, 20);
WMMoveWidget(panel->colorListHistoryBtn, 0, 0);
panel->colorListContentLst = WMCreateList(panel->colorListFrm);
WMSetListAction(panel->colorListContentLst, colorListSelect, panel);
WMSetListUserDrawProc(panel->colorListContentLst, colorListPaintItem);
WMResizeWidget(panel->colorListContentLst, PWIDTH - 8, PHEIGHT - 156);
WMMoveWidget(panel->colorListContentLst, 0, 23);
WMHangData(panel->colorListContentLst, panel);
panel->colorListColorMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
WMSetPopUpButtonPullsDown(panel->colorListColorMenuBtn, 1);
WMSetPopUpButtonText(panel->colorListColorMenuBtn, "Color");
WMSetPopUpButtonAction(panel->colorListColorMenuBtn,
colorListColorMenuCallback, panel);
WMResizeWidget(panel->colorListColorMenuBtn, (PWIDTH - 16)/2, 20);
WMMoveWidget(panel->colorListColorMenuBtn, 0, PHEIGHT - 130);
WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Add...");
WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Rename...");
WMAddPopUpButtonItem(panel->colorListColorMenuBtn, "Remove");
WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuAdd, 0);
WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRename, 0);
WMSetPopUpButtonItemEnabled(panel->colorListColorMenuBtn, CLmenuRemove, 0);
panel->colorListListMenuBtn = WMCreatePopUpButton(panel->colorListFrm);
WMSetPopUpButtonPullsDown(panel->colorListListMenuBtn, 1);
WMSetPopUpButtonText(panel->colorListListMenuBtn, "List");
WMSetPopUpButtonAction(panel->colorListListMenuBtn,
colorListListMenuCallback, panel);
WMResizeWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2, 20);
WMMoveWidget(panel->colorListListMenuBtn, (PWIDTH - 16)/2 + 8,
PHEIGHT - 130);
WMAddPopUpButtonItem(panel->colorListListMenuBtn, "New...");
WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Rename...");
WMAddPopUpButtonItem(panel->colorListListMenuBtn, "Remove");
WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuAdd, 0);
WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRename, 0);
WMSetPopUpButtonItemEnabled(panel->colorListListMenuBtn, CLmenuRemove, 0);
WMRealizeWidget(panel->win);
WMMapSubwidgets(panel->win);
WMMapSubwidgets(panel->wheelFrm);
WMMapSubwidgets(panel->slidersFrm);
WMMapSubwidgets(panel->grayFrm);
WMMapSubwidgets(panel->rgbFrm);
WMMapSubwidgets(panel->cmykFrm);
WMMapSubwidgets(panel->hsbFrm);
WMMapSubwidgets(panel->customPaletteFrm);
WMMapSubwidgets(panel->customPaletteContentFrm);
WMMapSubwidgets(panel->colorListFrm);
/* Pixmap to indicate selection positions
* wheelframe MUST be mapped.
*/
panel->selectionImg = XCreatePixmap(scrPtr->display,
WMWidgetXID(panel->win), 4, 4, scrPtr->depth);
XFillRectangle(scrPtr->display, panel->selectionImg, bgc, 0, 0, 4, 4);
XFillRectangle(scrPtr->display, panel->selectionImg, wgc, 1, 1, 2, 2);
readConfiguration(panel);
readXColors(panel);
return panel;
}
WMColorPanel*
WMGetColorPanel(WMScreen *scrPtr)
{
WMColorPanel *panel;
if (scrPtr->sharedColorPanel)
return scrPtr->sharedColorPanel;
panel = makeColorPanel(scrPtr, "colorPanel");
scrPtr->sharedColorPanel = panel;
return panel;
}
void
WMFreeColorPanel(WMColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
if (panel == scr->sharedColorPanel) {
scr->sharedColorPanel = NULL;
}
if (!panel)
return;
WMRemoveNotificationObserver(panel);
WMUnmapWidget(panel->win);
/* fonts */
WMReleaseFont(panel->font8);
WMReleaseFont(panel->font12);
/* pixmaps */
wheelDestroyMatrix(panel->wheelMtrx);
if (panel->wheelImg)
XFreePixmap(scr->display, panel->wheelImg);
if (panel->selectionImg)
XFreePixmap(scr->display, panel->selectionImg);
if (panel->selectionBackImg)
XFreePixmap(scr->display, panel->selectionBackImg);
RReleaseImage(panel->customPaletteImg);
/* structs */
if (panel->lastBrowseDir)
wfree(panel->lastBrowseDir);
if (panel->configurationPath)
wfree(panel->configurationPath);
WMDestroyWidget(panel->win);
wfree(panel);
}
void
WMCloseColorPanel(WMColorPanel *panel)
{
WMFreeColorPanel(panel);
}
void
WMShowColorPanel(WMColorPanel *panel)
{
WMScreen *scr = WMWidgetScreen(panel->win);
WMColor *white = WMWhiteColor(scr);
if (panel->color.set == cpNone)
WMSetColorPanelColor(panel, white);
WMReleaseColor(white);
if (panel->mode != WMWheelModeColorPanel)
WMPerformButtonClick(panel->wheelBtn);
WMMapWidget(panel->win);
}
static void
closeWindowCallback(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)data;
WMCloseColorPanel(panel);
}
static void
readConfiguration(W_ColorPanel *panel)
{
/* XXX Doesn't take care of "invalid" files */
DIR *dPtr;
struct dirent *dp;
struct stat stat_buf;
int item;
if (stat(panel->configurationPath, &stat_buf)!=0) {
if (mkdir(panel->configurationPath,
S_IRWXU|S_IRGRP|S_IROTH|S_IXGRP|S_IXOTH)!=0) {
wsyserror("Color Panel: Could not create directory %s needed"
" to store configurations", panel->configurationPath);
WMSetPopUpButtonEnabled(panel->customPaletteMenuBtn, False);
WMSetPopUpButtonEnabled(panel->colorListColorMenuBtn, False);
WMSetPopUpButtonEnabled(panel->colorListListMenuBtn, False);
WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
"File Error",
"Could not create ColorPanel configuration directory",
"OK", NULL, NULL);
}
return;
}
if (!(dPtr = opendir(panel->configurationPath))) {
wwarning(NO_FILE_ERR, "%s", panel->configurationPath);
return;
}
while ((dp = readdir(dPtr)) != NULL) {
unsigned int perm_mask;
char *path = wstrconcat(panel->configurationPath,
dp->d_name);
if (dp->d_name[0] != '.') {
item = WMGetPopUpButtonNumberOfItems(
panel->customPaletteHistoryBtn);
WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, dp->d_name);
perm_mask = (access(path, R_OK) == 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteHistoryBtn,
item, perm_mask);
}
wfree(path);
}
(void)closedir(dPtr);
}
static void
readXColors(W_ColorPanel *panel)
{
struct stat stat_buf;
FILE *rgbtxt;
char line[MAX_LENGTH];
int red, green, blue;
char name[48];
RColor *color;
WMListItem *item;
if (stat(RGBTXT, &stat_buf) != 0) {
wsyserror(NO_FILE_ERR, " %s", RGBTXT);
return;
}
else {
if ((rgbtxt = fopen(RGBTXT, "r"))) {
while (fgets(line, MAX_LENGTH, rgbtxt)) {
if (sscanf(line, "%d%d%d %[^\n]", &red, &green, &blue, name)) {
color = wmalloc(sizeof(RColor));
color->red = (unsigned char)red;
color->green = (unsigned char)green;
color->blue = (unsigned char)blue;
item = WMAddListItem(panel->colorListContentLst, name);
item->clientData = (void *)color;
}
}
fclose(rgbtxt);
}
else {
wsyserror(NO_FILE_ERR, "%s", RGBTXT);
}
}
}
void
WMSetColorPanelPickerMode(WMColorPanel *panel, WMColorPanelMode mode)
{
W_Screen *scr = WMWidgetScreen(panel->win);
if (mode != WMWheelModeColorPanel) {
WMUnmapWidget(panel->wheelFrm);
if (panel->selectionBackImg) {
XFreePixmap(WMWidgetScreen(panel->win)->display,
panel->selectionBackImg);
panel->selectionBackImg = None;
}
}
if (mode != WMGrayModeColorPanel)
WMUnmapWidget(panel->grayFrm);
if (mode != WMRGBModeColorPanel)
WMUnmapWidget(panel->rgbFrm);
if (mode != WMCMYKModeColorPanel)
WMUnmapWidget(panel->cmykFrm);
if (mode != WMHSBModeColorPanel)
WMUnmapWidget(panel->hsbFrm);
if (mode != WMCustomPaletteModeColorPanel) {
WMUnmapWidget(panel->customPaletteFrm);
if (panel->selectionBackImg) {
XFreePixmap(WMWidgetScreen(panel->win)->display,
panel->selectionBackImg);
panel->selectionBackImg = None;
}
}
if (mode != WMColorListModeColorPanel)
WMUnmapWidget(panel->colorListFrm);
if ((mode != WMGrayModeColorPanel) && (mode != WMRGBModeColorPanel) &&
(mode != WMCMYKModeColorPanel) && (mode != WMHSBModeColorPanel))
WMUnmapWidget(panel->slidersFrm);
else
panel->slidersmode = mode;
if (mode == WMWheelModeColorPanel) {
WMMapWidget(panel->wheelFrm);
WMSetButtonSelected(panel->wheelBtn, True);
if (panel->lastChanged != WMWheelModeColorPanel)
wheelInit(panel);
wheelRender(panel);
wheelPaint(panel);
} else if (mode == WMGrayModeColorPanel) {
WMMapWidget(panel->slidersFrm);
WMSetButtonSelected(panel->slidersBtn, True);
WMMapWidget(panel->grayFrm);
WMSetButtonSelected(panel->grayBtn, True);
WMSetButtonImage(panel->slidersBtn, scr->grayIcon);
if (panel->lastChanged != WMGrayModeColorPanel)
grayInit(panel);
} else if (mode == WMRGBModeColorPanel) {
WMMapWidget(panel->slidersFrm);
WMSetButtonSelected(panel->slidersBtn, True);
WMMapWidget(panel->rgbFrm);
WMSetButtonSelected(panel->rgbBtn, True);
WMSetButtonImage(panel->slidersBtn, scr->rgbIcon);
if (panel->lastChanged != WMRGBModeColorPanel)
rgbInit(panel);
} else if (mode == WMCMYKModeColorPanel) {
WMMapWidget(panel->slidersFrm);
WMSetButtonSelected(panel->slidersBtn, True);
WMMapWidget(panel->cmykFrm);
WMSetButtonSelected(panel->cmykBtn, True);
WMSetButtonImage(panel->slidersBtn, scr->cmykIcon);
if (panel->lastChanged != WMCMYKModeColorPanel)
cmykInit(panel);
} else if (mode == WMHSBModeColorPanel) {
WMMapWidget(panel->slidersFrm);
WMSetButtonSelected(panel->slidersBtn, True);
WMMapWidget(panel->hsbFrm);
WMSetButtonSelected(panel->hsbBtn, True);
WMSetButtonImage(panel->slidersBtn, scr->hsbIcon);
if (panel->lastChanged != WMHSBModeColorPanel)
hsbInit(panel);
} else if (mode == WMCustomPaletteModeColorPanel) {
WMMapWidget(panel->customPaletteFrm);
WMSetButtonSelected(panel->customPaletteBtn, True);
customSetPalette(panel);
} else if (mode == WMColorListModeColorPanel) {
WMMapWidget(panel->colorListFrm);
WMSetButtonSelected(panel->colorListBtn, True);
}
panel->mode = mode;
}
WMColor*
WMGetColorPanelColor(WMColorPanel *panel)
{
return WMGetColorWellColor(panel->colorWell);
}
void
WMSetColorPanelColor(WMColorPanel *panel, WMColor *color)
{
WMSetColorWellColor(panel->colorWell, color);
panel->color.rgb.red = color->color.red >> 8;
panel->color.rgb.green = color->color.green >> 8;
panel->color.rgb.blue = color->color.blue >> 8;
panel->color.set = cpRGB;
if (panel->mode == panel->lastChanged)
panel->lastChanged = 0;
WMSetColorPanelPickerMode(panel, panel->mode);
}
static void
updateSwatch(WMColorPanel *panel, CPColor color)
{
WMScreen *scr = WMWidgetScreen(panel->win);
WMColor *wellcolor;
if (color.set != cpRGB)
convertCPColor(&color);
panel->color = color;
wellcolor = WMCreateRGBColor(scr, color.rgb.red << 8,
color.rgb.green << 8,
color.rgb.blue << 8, True);
WMSetColorWellColor(panel->colorWell, wellcolor);
WMReleaseColor(wellcolor);
if (!panel->flags.dragging || panel->flags.continuous) {
if (panel->action)
(*panel->action)(panel, panel->clientData);
WMPostNotificationName(WMColorPanelColorChangedNotification, panel,
NULL);
}
}
static void
modeButtonCallback(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)(data);
if (w == panel->wheelBtn)
WMSetColorPanelPickerMode(panel, WMWheelModeColorPanel);
else if (w == panel->slidersBtn)
WMSetColorPanelPickerMode(panel, panel->slidersmode);
else if (w == panel->customPaletteBtn)
WMSetColorPanelPickerMode(panel, WMCustomPaletteModeColorPanel);
else if (w == panel->colorListBtn)
WMSetColorPanelPickerMode(panel, WMColorListModeColorPanel);
else if (w == panel->grayBtn)
WMSetColorPanelPickerMode(panel, WMGrayModeColorPanel);
else if (w == panel->rgbBtn)
WMSetColorPanelPickerMode(panel, WMRGBModeColorPanel);
else if (w == panel->cmykBtn)
WMSetColorPanelPickerMode(panel, WMCMYKModeColorPanel);
else if (w == panel->hsbBtn)
WMSetColorPanelPickerMode(panel, WMHSBModeColorPanel);
}
/****************** Magnifying Cursor Functions *******************/
static XImage*
magnifyGetImage(WMScreen *scr, XImage *image, int x, int y, int w, int h)
{
int x0 = 0, y0 = 0, w0 = w, h0 = h;
const int displayWidth = DisplayWidth(scr->display, scr->screen),
displayHeight = DisplayHeight(scr->display, scr->screen);
if (!(image && image->data)) {
/* The image in panel->magnifyGlass->image does not exist yet.
* Grab one from the screen (not beyond) and use it from now on.
*/
if (!(image = XGetImage(scr->display, scr->rootWin,
x - Cursor_x_hot,
y - Cursor_y_hot,
w, h, AllPlanes, ZPixmap)))
wwarning(X_ERR);
return image;
}
/* Coordinate correction for back pixmap
* if magnifying glass is at screen-borders
*/
/* Figure 1: Shifting of rectangle-to-grab at top/left screen borders
* Hatched area is beyond screen border.
*
* |<-Cursor_x_hot->|
* ________________|_____
* |/ / / / / / /| | |
* | / / / / / / |(x,y) |
* |/_/_/_/_/_/_/|________|
* |<----x0----->|<--w0-->|
* 0
*/
/* Figure 2: Shifting of rectangle-to-grab at bottom/right
* screen borders
* Hatched area is beyond screen border
*
* |<-Cursor_x_hot->|
* ________________|_______________
* | | | / / / / / /|
* | (x,y)|/ / / / / / |
* |___________________|_/_/_/_/_/_/|
* |<-------w0-------->| |
* |<---------------w--|----------->|
* | |
* x0 Displaywidth-1
*/
if (x < Cursor_x_hot) { /* see fig. 1 */
x0 = Cursor_x_hot - x;
w0 = w - x0;
}
if (displayWidth -1 < x - Cursor_x_hot + w) { /* see fig. 2 */
w0 = (displayWidth) - (x - Cursor_x_hot);
}
if (y < Cursor_y_hot) { /* see fig. 1 */
y0 = Cursor_y_hot - y;
h0 = h - y0;
}
if (displayHeight -1 < y - Cursor_y_hot + h) { /* see fig. 2 */
h0 = (displayHeight) - (y - Cursor_y_hot);
}
/* end of coordinate correction */
/* Grab an image from the screen, clipped if necessary,
* and put it in the existing panel->magnifyGlass->image
* with the corresponding clipping offset.
*/
if (!XGetSubImage(scr->display, scr->rootWin,
x - Cursor_x_hot + x0,
y - Cursor_y_hot + y0,
w0, h0, AllPlanes, ZPixmap,
image, x0, y0))
wwarning(X_ERR);
return NULL;
}
static void
magnifyGetImageStored(WMColorPanel *panel, int x1, int y1, int x2, int y2)
{
/* (x1, y1) = topleft corner of existing rectangle
* (x2, y2) = topleft corner of new position
*/
W_Screen *scr = WMWidgetScreen(panel->win);
int xa = 0, ya = 0, xb = 0, yb = 0;
int width, height;
const int dx = abs(x2 - x1),
dy = abs(y2 - y1);
XImage *image;
const int x_min = Cursor_x_hot,
y_min = Cursor_y_hot,
x_max = DisplayWidth(scr->display, scr->screen) -1 -
(Cursor_mask_width - Cursor_x_hot),
y_max = DisplayHeight(scr->display, scr->screen) -1 -
(Cursor_mask_height - Cursor_y_hot);
if ((dx == 0) && (dy == 0) && panel->magnifyGlass->image)
return; /* No movement */
if (x1 < x2)
xa = dx;
else
xb = dx;
if (y1 < y2)
ya = dy;
else
yb = dy;
width = Cursor_mask_width - dx;
height = Cursor_mask_height - dy;
/* If the traversed distance is larger than the size of the magnifying
* glass contents, there is no need to do dirty rectangles. A whole new
* rectangle can be grabbed (unless that rectangle falls partially
* off screen).
* Destroying the image and setting it to NULL will achieve that later on.
*
* Of course, grabbing an XImage beyond the borders of the screen will
* cause trouble, this is considdered a special case. Part of the screen
* is grabbed, but there is no need for dirty rectangles.
*/
if ((width <= 0) || (height <= 0)) {
if ((x2 >= x_min) && (y2 >= y_min) && (x2 <= x_max) && (y2 <= y_max)) {
if (panel->magnifyGlass->image)
XDestroyImage(panel->magnifyGlass->image);
panel->magnifyGlass->image = NULL;
}
} else {
if (panel->magnifyGlass->image) {
/* Get dirty rectangle from panel->magnifyGlass->image */
panel->magnifyGlass->dirtyRect =
XSubImage(panel->magnifyGlass->image, xa, ya, width, height);
if (!panel->magnifyGlass->dirtyRect) {
wwarning(X_ERR);
return; /* X returned a NULL from XSubImage */
}
}
}
/* Get image from screen */
image = magnifyGetImage(scr, panel->magnifyGlass->image, x2, y2,
Cursor_mask_width, Cursor_mask_height);
if (image) { /* Only reassign if a *new* image was grabbed */
panel->magnifyGlass->image = image;
return;
}
/* Copy previously stored rectangle on covered part of image */
if (panel->magnifyGlass->image && panel->magnifyGlass->dirtyRect) {
int old_height;
/* "width" and "height" are used as coordinates here,
* and run from [0...width-1] and [0...height-1] respectively.
*/
width--;
height--;
old_height = height;
for (; width >= 0; width--)
for (height = old_height; height >= 0; height--)
XPutPixel(panel->magnifyGlass->image, xb + width, yb + height,
XGetPixel(panel->magnifyGlass->dirtyRect, width, height));
XDestroyImage(panel->magnifyGlass->dirtyRect);
panel->magnifyGlass->dirtyRect = NULL;
}
return;
}
static Pixmap
magnifyCreatePixmap(WMColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
int u, v;
#ifndef SHAPE
Pixmap pixmap;
#endif
unsigned long color;
if (!panel->magnifyGlass->image)
return None;
if (!panel->magnifyGlass->magPix)
return None;
/*
* Copy an area of only 5x5 pixels from the center of the image.
*/
for (u = 0; u < 5; u++) {
for (v = 0; v < 5; v++) {
color = XGetPixel(panel->magnifyGlass->image, u + 9, v + 9);
XSetForeground(scr->display, scr->copyGC, color);
if ((u == 2) && (v == 2)) /* (2,2) is center pixel (unmagn.) */
panel->magnifyGlass->color = ulongToRColor(scr, color);
/* The center square must eventually be centered around the
* hotspot. The image needs shifting to achieve this. The amount of
* shifting is (Cursor_mask_width/2 - 2 * square_size) = 11-10 = 1
* _ _ _ _ _
* |_|_|_|_|_|
* ^------- center of center square == Cursor_x_hot
*/
XFillRectangle(scr->display, panel->magnifyGlass->magPix,
scr->copyGC,
u * 5 + (u == 0 ? 0 : -1), v * 5 + (v == 0 ? 0 : -1),
(u == 0 ? 4 : 5), (v == 0 ? 4 : 5));
}
}
#ifdef SHAPE
return panel->magnifyGlass->magPix;
#else
pixmap = XCreatePixmap(scr->display, W_DRAWABLE(scr), Cursor_mask_width,
Cursor_mask_height, scr->depth);
if (!pixmap)
return None;
XPutImage(scr->display, pixmap, scr->copyGC, panel->magnifyGlass->image,
0, 0, 0, 0, Cursor_mask_width, Cursor_mask_height);
/* Copy the magnified pixmap, with the clip mask, to background pixmap */
XCopyArea(scr->display, panel->magnifyGlass->magPix, pixmap,
scr->clipGC, 0, 0, Cursor_mask_width, Cursor_mask_height, 0, 0);
/* (2,2) puts center pixel on center of glass */
return pixmap;
#endif
}
static WMView*
magnifyCreateView(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
WMView *magView;
magView = W_CreateTopView(scr);
if (!magView)
return NULL;
magView->self = panel->win;
magView->flags.topLevel = 1;
magView->attribFlags |= CWOverrideRedirect | CWSaveUnder;
magView->attribs.override_redirect = True;
magView->attribs.save_under = True;
W_ResizeView(magView, Cursor_mask_width, Cursor_mask_height);
W_RealizeView(magView);
return magView;
}
static Cursor
magnifyGrabPointer(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
Pixmap magPixmap, magPixmap2;
Cursor magCursor;
XColor fgColor = {0, 0,0,0, DoRed|DoGreen|DoBlue};
XColor bgColor = {0, 0xbf00, 0xa000, 0x5000, DoRed|DoGreen|DoBlue};
/* Cursor creation stuff */
magPixmap = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_bits, Cursor_width, Cursor_height, 1, 0, 1);
magPixmap2 = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_shape_bits, Cursor_width, Cursor_height, 1, 0, 1);
magCursor = XCreatePixmapCursor(scr->display, magPixmap, magPixmap2,
&fgColor, &bgColor, Cursor_x_hot, Cursor_y_hot);
XFreePixmap(scr->display, magPixmap);
XFreePixmap(scr->display, magPixmap2);
XRecolorCursor(scr->display, magCursor, &fgColor, &bgColor);
/* Set up Pointer */
XGrabPointer (scr->display, panel->magnifyGlass->view->window, True,
PointerMotionMask | ButtonPressMask,
GrabModeAsync, GrabModeAsync,
scr->rootWin, magCursor, CurrentTime);
return magCursor;
}
static WMPoint
magnifyInitialize(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
int x, y, u, v;
unsigned int mask;
Pixmap pixmap, clip_mask;
WMPoint point;
Window root_return, child_return;
clip_mask = XCreatePixmapFromBitmapData(scr->display, W_DRAWABLE(scr),
(char *)Cursor_mask_bits, Cursor_mask_width, Cursor_mask_height,
1, 0, 1);
panel->magnifyGlass->magPix = XCreatePixmap(scr->display, W_DRAWABLE(scr),
5*5 -1, 5*5 -1, scr->depth);
XQueryPointer(scr->display, scr->rootWin, &root_return, &child_return,
&x, &y, &u, &v, &mask);
panel->magnifyGlass->image = NULL;
/* Clipmask to make magnified view-contents circular */
#ifdef SHAPE
XShapeCombineMask(scr->display, WMViewXID(panel->magnifyGlass->view),
ShapeBounding, 0, 0, clip_mask, ShapeSet);
#else
/* Clip circle in glass cursor */
XSetClipMask(scr->display, scr->clipGC, clip_mask);
XSetClipOrigin(scr->display, scr->clipGC, 0, 0);
#endif
XFreePixmap(scr->display, clip_mask);
/* Draw initial magnifying glass contents */
magnifyGetImageStored(panel, x, y, x, y);
pixmap = magnifyCreatePixmap(panel);
XSetWindowBackgroundPixmap(scr->display,
WMViewXID(panel->magnifyGlass->view),
pixmap);
XClearWindow(scr->display, WMViewXID(panel->magnifyGlass->view));
XFlush(scr->display);
#ifndef SHAPE
XFreePixmap(scr->display, pixmap);
#endif
point.x = x;
point.y = y;
return point;
}
static void
magnifyPutCursor(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)(data);
W_Screen *scr = WMWidgetScreen(panel->win);
Cursor magCursor;
Pixmap pixmap;
XEvent event;
WMPoint initialPosition;
/* Destroy wheelBackImg, so it'll update properly */
if (panel->selectionBackImg) {
XFreePixmap(WMWidgetScreen(panel->win)->display,
panel->selectionBackImg);
panel->selectionBackImg = None;
}
/* Create magnifying glass */
panel->magnifyGlass = wmalloc(sizeof(MovingView));
panel->magnifyGlass->view = magnifyCreateView(panel);
if (!panel->magnifyGlass->view)
return;
initialPosition = magnifyInitialize(panel);
panel->magnifyGlass->x = initialPosition.x;
panel->magnifyGlass->y = initialPosition.y;
W_MoveView(panel->magnifyGlass->view,
panel->magnifyGlass->x - Cursor_x_hot,
panel->magnifyGlass->y - Cursor_y_hot);
W_MapView(panel->magnifyGlass->view);
magCursor = magnifyGrabPointer(panel);
while (panel->magnifyGlass->image)
{
WMNextEvent(scr->display, &event);
/* Pack motion events */
while (XCheckTypedEvent(scr->display, MotionNotify, &event)) {
}
switch (event.type)
{
case ButtonPress:
XDestroyImage(panel->magnifyGlass->image);
panel->magnifyGlass->image = NULL;
if (event.xbutton.button == Button1) {
panel->color.rgb = panel->magnifyGlass->color;
panel->color.set = cpRGB;
updateSwatch(panel, panel->color);
}
switch (panel->mode) {
case WMWheelModeColorPanel:
wheelInit(panel);
wheelRender(panel);
wheelPaint(panel);
break;
case WMGrayModeColorPanel:
grayInit(panel);
break;
case WMRGBModeColorPanel:
rgbInit(panel);
break;
case WMCMYKModeColorPanel:
cmykInit(panel);
break;
case WMHSBModeColorPanel:
hsbInit(panel);
break;
default:
break;
}
panel->lastChanged = panel->mode;
WMSetButtonSelected(panel->magnifyBtn, False);
break;
case MotionNotify:
while (XPending(event.xmotion.display)) {
XEvent ev;
XPeekEvent(event.xmotion.display, &ev);
if (ev.type == MotionNotify)
XNextEvent(event.xmotion.display, &event);
else
break;
}
/* Get a "dirty rectangle" */
magnifyGetImageStored( panel,
panel->magnifyGlass->x, panel->magnifyGlass->y,
event.xmotion.x_root, event.xmotion.y_root);
/* Update coordinates */
panel->magnifyGlass->x = event.xmotion.x_root;
panel->magnifyGlass->y = event.xmotion.y_root;
/* Move view */
W_MoveView(panel->magnifyGlass->view,
panel->magnifyGlass->x - Cursor_x_hot,
panel->magnifyGlass->y - Cursor_y_hot);
/* Put new image (with magn.) in view */
pixmap = magnifyCreatePixmap(panel);
if (pixmap != None) {
/* Change the window background */
XSetWindowBackgroundPixmap(scr->display,
WMViewXID(panel->magnifyGlass->view), pixmap);
/* Force an Expose (handled by X) */
XClearWindow(scr->display,
WMViewXID(panel->magnifyGlass->view));
/* Synchronize the event queue, so the Expose is handled NOW */
XFlush(scr->display);
#ifndef SHAPE
XFreePixmap(scr->display, pixmap);
#endif
}
break;
/* Try XQueryPointer for this !!! It returns windows that the pointer
* is over. Note: We found this solving the invisible donkey cap bug
*/
#if 0 /* As it is impossible to make this work in all cases,
* we consider it confusing. Therefore we disabled it.
*/
case FocusOut: /* fall through */
case FocusIn:
/*
* Color Panel window (panel->win) lost or received focus.
* We need to update the pixmap in the magnifying glass.
*
* BUG Doesn't work with focus switches between two windows
* if none of them is the color panel.
*/
XUngrabPointer(scr->display, CurrentTime);
W_UnmapView(panel->magnifyGlass->view);
magnifyInitialize(panel);
W_MapView(panel->magnifyGlass->view);
XGrabPointer (scr->display, panel->magnifyGlass->view->window,
True, PointerMotionMask | ButtonPressMask,
GrabModeAsync, GrabModeAsync,
scr->rootWin, magCursor, CurrentTime);
break;
#endif
default:
WMHandleEvent(&event);
break;
} /* of switch */
}
XUngrabPointer(scr->display, CurrentTime);
XFreeCursor(scr->display, magCursor);
XFreePixmap(scr->display, panel->magnifyGlass->magPix);
panel->magnifyGlass->magPix = None;
W_UnmapView(panel->magnifyGlass->view);
W_DestroyView(panel->magnifyGlass->view);
panel->magnifyGlass->view = NULL;
wfree(panel->magnifyGlass);
}
/****************** ColorWheel Functions ************************/
static wheelMatrix*
wheelCreateMatrix(unsigned int width, unsigned int height)
{
wheelMatrix *matrix = NULL;
int i;
assert((width > 0) && (height > 0));
matrix = wmalloc(sizeof(wheelMatrix));
memset(matrix, 0, sizeof(wheelMatrix));
matrix->width = width;
matrix->height = height;
for (i = 0; i < 3; i++) {
matrix->data[i] = wmalloc(width*height*sizeof(unsigned char));
}
return matrix;
}
static void
wheelDestroyMatrix(wheelMatrix *matrix)
{
int i;
if (!matrix)
return;
for (i = 0; i < 3; i++) {
if (matrix->data[i])
wfree(matrix->data[i]);
}
wfree(matrix);
}
static void
wheelInitMatrix(W_ColorPanel *panel)
{
int i;
int x,y;
unsigned char *rp, *gp, *bp;
CPColor cpColor;
long ofs[4];
int xcor, ycor;
unsigned short sat;
int dhue[4];
const int cw_halfsize = (colorWheelSize + 4)/2,
cw_sqsize = (colorWheelSize +4) * (colorWheelSize +4),
uchar_shift = getShift(sizeof(unsigned char));
if (!panel->wheelMtrx)
return;
cpColor.hsv.value = 255;
cpColor.set = cpHSV;
ofs[0] = -1;
ofs[1] = -(colorWheelSize + 4);
/* offsets are counterclockwise (in triangles).
*
* ofs[0] ---->
* _______________________________________
* [1] |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| o
* s |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| f
* f |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_| s
* o | | | | | | | | | | | | | | | | | | | | | [3]
*
* <---- ofs[2]
* ____
* |\ /| <-- triangles
* | \/ |
* | /\ |
* |/__\|
*/
for (y = 0; y < cw_halfsize; y++) {
for (x = y; x < (colorWheelSize+4-y); x++) {
/* (xcor, ycor) is (x,y) relative to center of matrix */
xcor = 2 * x - 4 - colorWheelSize;
ycor = 2 * y - 4 - colorWheelSize;
/* RColor.saturation is unsigned char and will wrap after 255 */
sat = rint(255.0 * sqrt(xcor*xcor + ycor*ycor) / colorWheelSize);
cpColor.hsv.saturation = (unsigned char)sat;
ofs[0]++; /* top quarter of matrix*/
ofs[1] += colorWheelSize + 4; /* left quarter */
ofs[2] = cw_sqsize - 1 - ofs[0]; /* bottom quarter */
ofs[3] = cw_sqsize - 1 - ofs[1]; /* right quarter */
if (sat < 256) {
if (xcor != 0)
dhue[0] = rint(atan((double)ycor / (double)xcor) *
(180.0 / M_PI)) + (xcor < 0 ? 180.0 : 0.0);
else
dhue[0] = 270;
dhue[0] = 360 - dhue[0]; /* Reverse direction of ColorWheel */
dhue[1] = 270 - dhue[0] + (dhue[0] > 270 ? 360 : 0);
dhue[2] = dhue[0] - 180 + (dhue[0] < 180 ? 360 : 0);
dhue[3] = 90 - dhue[0] + (dhue[0] > 90 ? 360 : 0);
for (i = 0; i < 4; i++) {
rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
cpColor.hsv.hue = dhue[i];
convertCPColor(&cpColor);
*rp = (unsigned char)(cpColor.rgb.red);
*gp = (unsigned char)(cpColor.rgb.green);
*bp = (unsigned char)(cpColor.rgb.blue);
}
}
else {
for (i = 0; i < 4; i++) {
rp = panel->wheelMtrx->data[0] + (ofs[i] << uchar_shift);
gp = panel->wheelMtrx->data[1] + (ofs[i] << uchar_shift);
bp = panel->wheelMtrx->data[2] + (ofs[i] << uchar_shift);
*rp = (unsigned char)0;
*gp = (unsigned char)0;
*bp = (unsigned char)0;
}
}
}
ofs[0] += 2*y+1;
ofs[1] += 1 - (colorWheelSize + 4) * (colorWheelSize + 4 - 1 - 2*y);
}
}
static void
wheelCalculateValues(W_ColorPanel *panel, int maxvalue)
{
unsigned int i;
unsigned int v;
for (i = 0; i < 256; i++) {
/* We divide by 128 in advance, and check whether that number divides
* by 2 properly. If not, we add one to round the number correctly
*/
v = (i*maxvalue) >> 7;
panel->wheelMtrx->values[i] = (unsigned char)((v >> 1) +(v & 0x01));
}
}
static void
wheelRender(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
int x,y;
RImage *image;
unsigned char *ptr;
RColor gray;
unsigned long ofs = 0;
/*unsigned char shift = getShift(sizeof(unsigned char));*/
image = RCreateImage(colorWheelSize+4, colorWheelSize+4, True);
if (!image) {
wwarning(NO_MEMORY_ERR);
return;
}
ptr = image->data;
/* TODO Make this transparent istead of gray */
gray.red = gray.blue = 0xae; gray.green = 0xaa;
for (y = 0; y < colorWheelSize+4; y++) {
for (x = 0; x < colorWheelSize+4; x++) {
if (wheelInsideColorWheel(panel, ofs)) {
*(ptr++) = (unsigned char)(panel->wheelMtrx->values[
panel->wheelMtrx->data[0][ofs] ]);
*(ptr++) = (unsigned char)(panel->wheelMtrx->values[
panel->wheelMtrx->data[1][ofs] ]);
*(ptr++) = (unsigned char)(panel->wheelMtrx->values[
panel->wheelMtrx->data[2][ofs] ]);
*(ptr++) = 0;
}
else {
*(ptr++) = (unsigned char)(gray.red);
*(ptr++) = (unsigned char)(gray.green);
*(ptr++) = (unsigned char)(gray.blue);
*(ptr++) = 255;
}
ofs++;
}
}
if (panel->wheelImg)
XFreePixmap(scr->display, panel->wheelImg);
RConvertImage(scr->rcontext, image, &panel->wheelImg);
RReleaseImage(image);
/* Check if backimage exists. If it doesn't, allocate and fill it */
if (!panel->selectionBackImg) {
panel->selectionBackImg = XCreatePixmap(scr->display,
W_VIEW(panel->wheelFrm)->window, 4, 4, scr->depth);
XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
/* -2 is hot spot correction */
}
}
static Bool
wheelInsideColorWheel(W_ColorPanel *panel, unsigned long ofs)
{
return ((panel->wheelMtrx->data[0][ofs] != 0) &&
(panel->wheelMtrx->data[1][ofs] != 0) &&
(panel->wheelMtrx->data[2][ofs] != 0));
}
static void
wheelPaint (W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
XCopyArea(scr->display, panel->wheelImg, panel->wheelView->window,
scr->copyGC, 0, 0, colorWheelSize+4, colorWheelSize+4, 0, 0);
/* Draw selection image */
XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
}
static void
wheelHandleEvents(XEvent *event, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)data;
switch (event->type) {
case Expose:
if (event->xexpose.count != 0) /* TODO Improve */
break;
wheelPaint(panel);
break;
}
}
static void
wheelHandleActionEvents(XEvent *event, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)data;
switch (event->type) {
case ButtonPress:
if (getPickerPart(panel, event->xbutton.x, event->xbutton.y) ==
COLORWHEEL_PART) {
panel->lastChanged = WMWheelModeColorPanel;
panel->flags.dragging = 1;
wheelPositionSelection(panel, event->xbutton.x, event->xbutton.y);
}
break;
case ButtonRelease:
panel->flags.dragging = 0;
if (!panel->flags.continuous) {
if (panel->action)
(*panel->action)(panel, panel->clientData);
}
break;
case MotionNotify:
if (panel->flags.dragging) {
if (getPickerPart(panel, event->xmotion.x, event->xmotion.y) ==
COLORWHEEL_PART) {
wheelPositionSelection(panel, event->xmotion.x,
event->xmotion.y);
}
else
wheelPositionSelectionOutBounds(panel, event->xmotion.x,
event->xmotion.y);
}
break;
}
}
static int
getPickerPart(W_ColorPanel *panel, int x, int y)
{
int lx, ly;
unsigned long ofs;
lx = x;
ly = y;
if (panel->mode == WMWheelModeColorPanel) {
if ((lx >= 2) && (lx <= 2+colorWheelSize) && (ly >= 2) &&
(ly <= 2+colorWheelSize)) {
ofs = ly*panel->wheelMtrx->width+lx;
if (wheelInsideColorWheel(panel, ofs))
return COLORWHEEL_PART;
}
}
if (panel->mode == WMCustomPaletteModeColorPanel) {
if ((lx >= 2) && (lx < customPaletteWidth-2) && (ly >= 2) &&
(ly < customPaletteHeight-2)) {
return CUSTOMPALETTE_PART;
}
}
return 0;
}
static void
wheelBrightnessSliderCallback(WMWidget *w, void *data)
{
int value;
W_ColorPanel *panel = (W_ColorPanel*)data;
value = 255-WMGetSliderValue(panel->wheelBrightnessS);
wheelCalculateValues(panel, value);
if (panel->color.set == cpRGB) {
convertCPColor(&panel->color);
panel->color.set = cpHSV;
}
panel->color.hsv.value = value;
wheelRender(panel);
wheelPaint(panel);
wheelUpdateSelection(panel);
}
static void
wheelUpdateSelection(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
updateSwatch(panel, panel->color);
panel->lastChanged = WMWheelModeColorPanel;
/* Redraw color selector (and make a backup of the part it will cover) */
XCopyArea(scr->display, panel->wheelImg, panel->selectionBackImg,
scr->copyGC, panel->colx -2, panel->coly -2, 4, 4, 0, 0);
/* "-2" is correction for hotspot location */
XCopyArea(scr->display, panel->selectionImg, panel->wheelView->window,
scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
/* see above */
}
static void
wheelUndrawSelection(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
XCopyArea(scr->display, panel->selectionBackImg, panel->wheelView->window,
scr->copyGC, 0, 0, 4, 4, panel->colx -2, panel->coly -2);
/* see above */
}
static void
wheelPositionSelection(W_ColorPanel *panel, int x, int y)
{
unsigned long ofs = (y * panel->wheelMtrx->width)+ x;
panel->color.rgb.red = panel->wheelMtrx->values[
panel->wheelMtrx->data[0][ofs] ];
panel->color.rgb.green = panel->wheelMtrx->values[
panel->wheelMtrx->data[1][ofs] ];
panel->color.rgb.blue = panel->wheelMtrx->values[
panel->wheelMtrx->data[2][ofs] ];
panel->color.set = cpRGB;
wheelUndrawSelection(panel);
panel->colx = x;
panel->coly = y;
wheelUpdateSelection(panel);
wheelUpdateBrightnessGradientFromLocation(panel);
}
static void
wheelPositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
{
int hue;
int xcor, ycor;
CPColor cpColor;
xcor = x * 2 - colorWheelSize - 4;
ycor = y * 2 - colorWheelSize - 4;
panel->color.hsv.saturation = 255;
panel->color.hsv.value = 255 - WMGetSliderValue(panel->wheelBrightnessS);
if (xcor != 0)
hue = rint(atan(- (double)ycor / (double)xcor) * (180.0/M_PI));
else {
if (ycor < 0)
hue = 90;
else
hue = 270;
}
if (xcor < 0)
hue += 180;
if ((xcor > 0) && (ycor > 0))
hue += 360;
panel->color.hsv.hue = hue;
panel->color.set = cpHSV;
convertCPColor(&panel->color);
wheelUndrawSelection(panel);
panel->colx = 2 + rint((colorWheelSize * (1.0 +
cos( panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
/* "+2" because of "colorWheelSize + 4" */
panel->coly = 2 + rint((colorWheelSize * (1.0 +
sin(- panel->color.hsv.hue * (M_PI/180.0) ))) / 2.0);
wheelUpdateSelection(panel);
cpColor = panel->color;
wheelUpdateBrightnessGradient(panel, cpColor);
}
static void
wheelUpdateBrightnessGradientFromLocation(W_ColorPanel *panel)
{
CPColor from;
unsigned long ofs;
ofs = panel->coly * panel->wheelMtrx->width + panel->colx;
from.rgb.red = panel->wheelMtrx->data[0][ofs];
from.rgb.green = panel->wheelMtrx->data[1][ofs];
from.rgb.blue = panel->wheelMtrx->data[2][ofs];
from.set = cpRGB;
wheelUpdateBrightnessGradient(panel, from);
}
static void
wheelUpdateBrightnessGradient(W_ColorPanel *panel, CPColor topColor)
{
RColor to;
RImage *sliderImg;
WMPixmap *sliderPxmp;
to.red = to.green = to.blue = 0;
if (topColor.set == cpHSV)
convertCPColor(&topColor);
sliderImg = RRenderGradient(16, 153, &(topColor.rgb), &to, RGRD_VERTICAL);
sliderPxmp = WMCreatePixmapFromRImage(WMWidgetScreen(panel->win),
sliderImg, 0);
RReleaseImage(sliderImg);
WMSetSliderImage(panel->wheelBrightnessS, sliderPxmp);
WMReleasePixmap(sliderPxmp);
}
/****************** Grayscale Panel Functions ***************/
static void
grayBrightnessSliderCallback(WMWidget *w, void *data)
{
CPColor cpColor;
int value;
char tmp[4];
W_ColorPanel *panel = (W_ColorPanel*)data;
value = WMGetSliderValue(panel->grayBrightnessS);
sprintf(tmp, "%d", value);
WMSetTextFieldText(panel->grayBrightnessT, tmp);
cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue = rint(2.55*value);
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMGrayModeColorPanel;
}
static void
grayPresetButtonCallback(WMWidget *w, void *data)
{
CPColor cpColor;
char tmp[4];
int value;
int i=0;
W_ColorPanel *panel = (W_ColorPanel*)data;
while (i < 7) {
if (w == panel->grayPresetBtn[i])
break;
i++;
}
value = rint((100.0*i)/6.0);
sprintf(tmp, "%d", value);
WMSetTextFieldText(panel->grayBrightnessT, tmp);
cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
rint((255.0*i)/6.0);
cpColor.set = cpRGB;
WMSetSliderValue(panel->grayBrightnessS, rint((100.0*i)/6.0));
updateSwatch(panel, cpColor);
panel->lastChanged = WMGrayModeColorPanel;
}
static void
grayBrightnessTextFieldCallback(void *observerData,
WMNotification *notification)
{
CPColor cpColor;
char tmp[4];
int value;
W_ColorPanel *panel = (W_ColorPanel*)observerData;
value = atoi(WMGetTextFieldText(panel->grayBrightnessT));
if (value > 100)
value = 100;
if (value < 0)
value = 0;
sprintf(tmp, "%d", value);
WMSetTextFieldText(panel->grayBrightnessT, tmp);
WMSetSliderValue(panel->grayBrightnessS, value);
cpColor.rgb.red = cpColor.rgb.green = cpColor.rgb.blue =
rint((255.0*value)/100.0);
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMGrayModeColorPanel;
}
/******************* RGB Panel Functions *****************/
static void
rgbSliderCallback(WMWidget *w, void *data)
{
CPColor cpColor;
int value[3];
char tmp[4];
W_ColorPanel *panel = (W_ColorPanel*)data;
value[0] = WMGetSliderValue(panel->rgbRedS);
value[1] = WMGetSliderValue(panel->rgbGreenS);
value[2] = WMGetSliderValue(panel->rgbBlueS);
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->rgbRedT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->rgbGreenT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->rgbBlueT, tmp);
cpColor.rgb.red = value[0];
cpColor.rgb.green = value[1];
cpColor.rgb.blue = value[2];
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMRGBModeColorPanel;
}
static void
rgbTextFieldCallback(void *observerData, WMNotification *notification)
{
CPColor cpColor;
int value[3];
char tmp[4];
int n;
W_ColorPanel *panel = (W_ColorPanel*)observerData;
value[0] = atoi(WMGetTextFieldText(panel->rgbRedT));
value[1] = atoi(WMGetTextFieldText(panel->rgbGreenT));
value[2] = atoi(WMGetTextFieldText(panel->rgbBlueT));
for (n=0; n < 3; n++) {
if (value[n] > 255)
value[n] = 255;
if (value[n] < 0)
value[n] = 0;
}
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->rgbRedT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->rgbGreenT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->rgbBlueT, tmp);
WMSetSliderValue(panel->rgbRedS, value[0]);
WMSetSliderValue(panel->rgbGreenS, value[1]);
WMSetSliderValue(panel->rgbBlueS, value[2]);
cpColor.rgb.red = value[0];
cpColor.rgb.green = value[1];
cpColor.rgb.blue = value[2];
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMRGBModeColorPanel;
}
/******************* CMYK Panel Functions *****************/
static void
cmykSliderCallback(WMWidget *w, void *data)
{
CPColor cpColor;
int value[4];
char tmp[4];
W_ColorPanel *panel = (W_ColorPanel*)data;
double scale;
value[0] = WMGetSliderValue(panel->cmykCyanS);
value[1] = WMGetSliderValue(panel->cmykMagentaS);
value[2] = WMGetSliderValue(panel->cmykYellowS);
value[3] = WMGetSliderValue(panel->cmykBlackS);
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->cmykCyanT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->cmykMagentaT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->cmykYellowT, tmp);
sprintf(tmp, "%d", value[3]);
WMSetTextFieldText(panel->cmykBlackT, tmp);
scale = 2.55 * (1.0 - (value[3] / 100.0));
cpColor.rgb.red = rint((100.0 - value[0]) * scale);
cpColor.rgb.green = rint((100.0 - value[1]) * scale);
cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMCMYKModeColorPanel;
}
static void
cmykTextFieldCallback(void *observerData, WMNotification *notification)
{
CPColor cpColor;
int value[4];
char tmp[4];
int n;
double scale;
W_ColorPanel *panel = (W_ColorPanel*)observerData;
value[0] = atoi(WMGetTextFieldText(panel->cmykCyanT));
value[1] = atoi(WMGetTextFieldText(panel->cmykMagentaT));
value[2] = atoi(WMGetTextFieldText(panel->cmykYellowT));
value[3] = atoi(WMGetTextFieldText(panel->cmykBlackT));
for (n=0; n < 4; n++) {
if (value[n] > 100)
value[n] = 100;
if (value[n] < 0)
value[n] = 0;
}
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->cmykCyanT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->cmykMagentaT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->cmykYellowT, tmp);
sprintf(tmp, "%d", value[3]);
WMSetTextFieldText(panel->cmykBlackT, tmp);
WMSetSliderValue(panel->cmykCyanS, value[0]);
WMSetSliderValue(panel->cmykMagentaS, value[1]);
WMSetSliderValue(panel->cmykYellowS, value[2]);
WMSetSliderValue(panel->cmykBlackS, value[3]);
scale = 2.55 * (1.0 - (value[3] / 100.0));
cpColor.rgb.red = rint((100.0 - value[0]) * scale);
cpColor.rgb.green = rint((100.0 - value[1]) * scale);
cpColor.rgb.blue = rint((100.0 - value[2]) * scale);
cpColor.set = cpRGB;
updateSwatch(panel, cpColor);
panel->lastChanged = WMCMYKModeColorPanel;
}
/********************** HSB Panel Functions ***********************/
static void
hsbSliderCallback(WMWidget *w, void *data)
{
CPColor cpColor;
int value[3];
char tmp[4];
W_ColorPanel *panel = (W_ColorPanel*)data;
value[0] = WMGetSliderValue(panel->hsbHueS);
value[1] = WMGetSliderValue(panel->hsbSaturationS);
value[2] = WMGetSliderValue(panel->hsbBrightnessS);
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->hsbHueT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->hsbSaturationT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->hsbBrightnessT, tmp);
cpColor.hsv.hue = value[0];
cpColor.hsv.saturation = value[1]*2.55;
cpColor.hsv.value = value[2]*2.55;
cpColor.set = cpHSV;
convertCPColor(&cpColor);
panel->lastChanged = WMHSBModeColorPanel;
updateSwatch(panel, cpColor);
if (w != panel->hsbBrightnessS)
hsbUpdateBrightnessGradient(panel);
if (w != panel->hsbSaturationS)
hsbUpdateSaturationGradient(panel);
if (w != panel->hsbHueS)
hsbUpdateHueGradient(panel);
}
static void
hsbTextFieldCallback(void *observerData, WMNotification *notification)
{
CPColor cpColor;
int value[3];
char tmp[4];
int n;
W_ColorPanel *panel = (W_ColorPanel*)observerData;
value[0] = atoi(WMGetTextFieldText(panel->hsbHueT));
value[1] = atoi(WMGetTextFieldText(panel->hsbSaturationT));
value[2] = atoi(WMGetTextFieldText(panel->hsbBrightnessT));
if (value[0] > 359)
value[0] = 359;
if (value[0] < 0)
value[0] = 0;
for (n=1; n < 3; n++) {
if (value[n] > 100)
value[n] = 100;
if (value[n] < 0)
value[n] = 0;
}
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->hsbHueT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->hsbSaturationT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->hsbBrightnessT, tmp);
WMSetSliderValue(panel->hsbHueS, value[0]);
WMSetSliderValue(panel->hsbSaturationS, value[1]);
WMSetSliderValue(panel->hsbBrightnessS, value[2]);
cpColor.hsv.hue = value[0];
cpColor.hsv.saturation = value[1]*2.55;
cpColor.hsv.value = value[2]*2.55;
cpColor.set = cpHSV;
convertCPColor(&cpColor);
panel->lastChanged = WMHSBModeColorPanel;
updateSwatch(panel, cpColor);
hsbUpdateBrightnessGradient(panel);
hsbUpdateSaturationGradient(panel);
hsbUpdateHueGradient(panel);
}
static void
hsbUpdateBrightnessGradient(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
RColor from;
CPColor to;
RImage *sliderImg;
WMPixmap *sliderPxmp;
from.red = from.green = from.blue = 0;
to.hsv = panel->color.hsv;
to.hsv.value = 255;
to.set = cpHSV;
convertCPColor(&to);
sliderImg = RRenderGradient(141, 16, &from, &(to.rgb), RGRD_HORIZONTAL);
sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
RReleaseImage(sliderImg);
if (sliderPxmp)
W_PaintText(W_VIEW(panel->hsbBrightnessS), sliderPxmp->pixmap,
panel->font12, 2, 0, 100, WALeft, WMColorGC(scr->white),
False, "Brightness", strlen("Brightness"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->hsbBrightnessS, sliderPxmp);
WMReleasePixmap(sliderPxmp);
}
static void
hsbUpdateSaturationGradient(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
CPColor from;
CPColor to;
RImage *sliderImg;
WMPixmap *sliderPxmp;
from.hsv = panel->color.hsv;
from.hsv.saturation = 0;
from.set = cpHSV;
convertCPColor(&from);
to.hsv = panel->color.hsv;
to.hsv.saturation = 255;
to.set = cpHSV;
convertCPColor(&to);
sliderImg = RRenderGradient(141, 16, &(from.rgb), &(to.rgb),
RGRD_HORIZONTAL);
sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
RReleaseImage(sliderImg);
if (sliderPxmp)
W_PaintText(W_VIEW(panel->hsbSaturationS), sliderPxmp->pixmap,
panel->font12, 2, 0, 100, WALeft,
WMColorGC(from.hsv.value < 128 ? scr->white : scr->black), False,
"Saturation", strlen("Saturation"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->hsbSaturationS, sliderPxmp);
WMReleasePixmap(sliderPxmp);
}
static void
hsbUpdateHueGradient(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
RColor **colors = NULL;
RHSVColor hsvcolor;
RImage *sliderImg;
WMPixmap *sliderPxmp;
int i;
hsvcolor = panel->color.hsv;
colors = wmalloc(sizeof(RColor*)*(8));
for (i=0; i<7; i++) {
hsvcolor.hue = (360*i)/6;
colors[i] = wmalloc(sizeof(RColor));
RHSVtoRGB(&hsvcolor, colors[i]);
}
colors[7] = NULL;
sliderImg = RRenderMultiGradient(141, 16, colors, RGRD_HORIZONTAL);
sliderPxmp = WMCreatePixmapFromRImage(scr, sliderImg, 0);
RReleaseImage(sliderImg);
if (sliderPxmp)
W_PaintText(W_VIEW(panel->hsbHueS), sliderPxmp->pixmap,
panel->font12, 2, 0, 100, WALeft,
WMColorGC(hsvcolor.value < 128 ? scr->white : scr->black), False,
"Hue", strlen("Hue"));
else
wwarning(NO_MEMORY_ERR);
WMSetSliderImage(panel->hsbHueS, sliderPxmp);
WMReleasePixmap(sliderPxmp);
for (i=0; i<7; i++)
wfree(colors[i]);
wfree(colors);
}
/*************** Custom Palette Functions ****************/
static void
customRenderSpectrum(W_ColorPanel *panel)
{
RImage *spectrum;
int x,y;
unsigned char *ptr;
CPColor cpColor;
spectrum = RCreateImage(SPECTRUM_WIDTH, SPECTRUM_HEIGHT, False);
ptr = spectrum->data;
for (y = 0; y < SPECTRUM_HEIGHT; y++) {
cpColor.hsv.hue = y;
cpColor.hsv.saturation = 0;
cpColor.hsv.value = 255;
cpColor.set = cpHSV;
for (x = 0; x < SPECTRUM_WIDTH; x++) {
convertCPColor(&cpColor);
*(ptr++) = (unsigned char)cpColor.rgb.red;
*(ptr++) = (unsigned char)cpColor.rgb.green;
*(ptr++) = (unsigned char)cpColor.rgb.blue;
if (x < (SPECTRUM_WIDTH/2))
cpColor.hsv.saturation++;
if (x > (SPECTRUM_WIDTH/2))
cpColor.hsv.value--;
}
}
if (panel->customPaletteImg) {
RReleaseImage(panel->customPaletteImg);
panel->customPaletteImg = NULL;
}
panel->customPaletteImg = spectrum;
}
static void
customSetPalette(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
RImage *scaledImg;
Pixmap image;
int item;
image = XCreatePixmap(scr->display, W_DRAWABLE(scr), customPaletteWidth,
customPaletteHeight, scr->depth);
scaledImg = RScaleImage(panel->customPaletteImg, customPaletteWidth,
customPaletteHeight);
RConvertImage(scr->rcontext, scaledImg, &image);
RReleaseImage(scaledImg);
XCopyArea(scr->display, image, panel->customPaletteContentView->window,
scr->copyGC, 0, 0, customPaletteWidth, customPaletteHeight, 0, 0);
/* Check backimage exists. If it doesn't, allocate and fill it */
if (!panel->selectionBackImg) {
panel->selectionBackImg = XCreatePixmap(scr->display,
panel->customPaletteContentView->window, 4, 4, scr->depth);
}
XCopyArea(scr->display, image, panel->selectionBackImg, scr->copyGC,
panel->palx-2, panel->paly-2, 4, 4, 0, 0);
XCopyArea(scr->display, panel->selectionImg,
panel->customPaletteContentView->window, scr->copyGC, 0 , 0, 4, 4,
panel->palx-2, panel->paly-2);
XFreePixmap(scr->display, image);
panel->palXRatio = (double)(panel->customPaletteImg->width) /
(double)(customPaletteWidth);
panel->palYRatio = (double)(panel->customPaletteImg->height) /
(double)(customPaletteHeight);
item = WMGetPopUpButtonSelectedItem (panel->customPaletteHistoryBtn);
}
static void
customPalettePositionSelection(W_ColorPanel *panel, int x, int y)
{
W_Screen *scr = WMWidgetScreen(panel->win);
unsigned long ofs;
/* undraw selection */
XCopyArea(scr->display, panel->selectionBackImg,
panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
panel->palx-2, panel->paly-2);
panel->palx = x;
panel->paly = y;
ofs = (rint(x * panel->palXRatio) + rint(y * panel->palYRatio) *
panel->customPaletteImg->width) * 3;
panel->color.rgb.red = panel->customPaletteImg->data[ofs];
panel->color.rgb.green = panel->customPaletteImg->data[ofs+1];
panel->color.rgb.blue = panel->customPaletteImg->data[ofs+2];
panel->color.set = cpRGB;
updateSwatch(panel, panel->color);
panel->lastChanged = WMCustomPaletteModeColorPanel;
/* Redraw color selector (and make a backup of the part it will cover) */
XCopyArea(scr->display, panel->customPaletteContentView->window,
panel->selectionBackImg, scr->copyGC, panel->palx-2, panel->paly-2,
4, 4, 0, 0); /* "-2" is correction for hotspot location */
XCopyArea(scr->display, panel->selectionImg,
panel->customPaletteContentView->window, scr->copyGC, 0, 0, 4, 4,
panel->palx-2, panel->paly-2); /* see above */
}
static void
customPalettePositionSelectionOutBounds(W_ColorPanel *panel, int x, int y)
{
if (x < 2)
x = 2;
if (y < 2)
y = 2;
if (x >= customPaletteWidth)
x = customPaletteWidth -2;
if (y >= customPaletteHeight)
y = customPaletteHeight -2;
customPalettePositionSelection(panel, x, y);
}
static void
customPaletteHandleEvents(XEvent *event, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)data;
switch (event->type) {
case Expose:
if (event->xexpose.count != 0) /* TODO Improve. */
break;
customSetPalette(panel);
break;
}
}
static void
customPaletteHandleActionEvents(XEvent *event, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)data;
int x, y;
switch (event->type) {
case ButtonPress:
x = event->xbutton.x;
y = event->xbutton.y;
if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
panel->flags.dragging = 1;
customPalettePositionSelection(panel, x, y);
}
break;
case ButtonRelease:
panel->flags.dragging = 0;
if (!panel->flags.continuous) {
if (panel->action)
(*panel->action)(panel, panel->clientData);
}
break;
case MotionNotify:
x = event->xmotion.x;
y = event->xmotion.y;
if (panel->flags.dragging) {
if (getPickerPart(panel, x, y) == CUSTOMPALETTE_PART) {
customPalettePositionSelection(panel, x, y);
}
else
customPalettePositionSelectionOutBounds(panel, x, y);
}
break;
}
}
static void
customPaletteMenuCallback(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)data;
int item = WMGetPopUpButtonSelectedItem(panel->customPaletteMenuBtn);
switch (item) {
case CPmenuNewFromFile:
customPaletteMenuNewFromFile(panel);
break;
case CPmenuRename:
customPaletteMenuRename(panel);
break;
case CPmenuRemove:
customPaletteMenuRemove(panel);
break;
case CPmenuCopy:
break;
case CPmenuNewFromClipboard:
break;
}
}
static void
customPaletteMenuNewFromFile(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
WMOpenPanel *browseP;
char *filepath;
char *filename = NULL;
char *spath;
char *tmp;
int i;
RImage *tmpImg = NULL;
if ((!panel->lastBrowseDir) || (strcmp(panel->lastBrowseDir,"\0") == 0))
spath = wexpandpath(wgethomedir());
else
spath = wexpandpath(panel->lastBrowseDir);
browseP = WMGetOpenPanel(scr);
WMSetFilePanelCanChooseDirectories(browseP, 0);
WMSetFilePanelCanChooseFiles(browseP, 1);
/* Get a filename */
if (WMRunModalFilePanelForDirectory(browseP, panel->win, spath,
"Open Palette", RSupportedFileFormats()) ) {
filepath = WMGetFilePanelFileName(browseP);
/* Get seperation position between path and filename */
i = strrchr(filepath, '/') - filepath + 1;
if (i > strlen(filepath))
i = strlen(filepath);
/* Store last browsed path */
if (panel->lastBrowseDir)
wfree(panel->lastBrowseDir);
panel->lastBrowseDir = wmalloc((i+1)*sizeof(char));
strncpy(panel->lastBrowseDir, filepath, i);
panel->lastBrowseDir[i] = '\0';
/* Get filename from path */
filename = wstrdup(filepath + i);
/* Check for duplicate files, and rename it if there are any */
tmp = wstrconcat(panel->configurationPath, filename);
while (access (tmp, F_OK) == 0) {
char *newName;
wfree(tmp);
newName = generateNewFilename(filename);
wfree(filename);
filename = newName;
tmp = wstrconcat(panel->configurationPath, filename);
}
wfree(tmp);
/* Copy image to $(gnustepdir)/Library/Colors/ &
* Add filename to history menu */
if (fetchFile (panel->configurationPath, filepath, filename) == 0) {
/* filepath is a "local" path now the file has been copied */
wfree(filepath);
filepath = wstrconcat(panel->configurationPath, filename);
/* load the image & add menu entries */
tmpImg = RLoadImage(scr->rcontext, filepath, 0);
if (tmpImg) {
if (panel->customPaletteImg)
RReleaseImage(panel->customPaletteImg);
panel->customPaletteImg = tmpImg;
customSetPalette(panel);
WMAddPopUpButtonItem(panel->customPaletteHistoryBtn, filename);
panel->currentPalette = WMGetPopUpButtonNumberOfItems(
panel->customPaletteHistoryBtn)-1;
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
panel->currentPalette);
}
} else {
tmp = wstrconcat(panel->configurationPath, filename);
i = remove(tmp); /* Delete the file, it doesn't belong here */
WMRunAlertPanel(scr, panel->win, "File Error",
"Invalid file format !", "OK", NULL, NULL);
if (i != 0) {
wsyserror("can't remove file %s", tmp);
WMRunAlertPanel(scr, panel->win, "File Error",
"Couldn't remove file from Configuration Directory !",
"OK", NULL, NULL);
}
wfree(tmp);
}
wfree(filepath);
wfree(filename);
}
WMFreeFilePanel(browseP);
wfree(spath);
}
static void
customPaletteMenuRename(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
char *toName = NULL;
char *fromName;
char *toPath, *fromPath;
int item;
int index;
item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
fromName = WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item);
toName = WMRunInputPanel(scr, panel->win, "Rename", "Rename palette to:",
fromName, "OK", "Cancel");
if (toName) {
/* As some people do certain stupid things... */
if (strcmp(toName, fromName) == 0) {
wfree(toName);
return;
}
/* For normal people */
fromPath = wstrconcat(panel->configurationPath, fromName);
toPath = wstrconcat(panel->configurationPath, toName);
if (access (toPath, F_OK) == 0) {
/* Careful, this palette exists already */
if (WMRunAlertPanel(scr, panel->win, "Warning",
"Palette already exists !\n\nOverwrite ?", "No", "Yes",
NULL) == 1) {
/* "No" = 0, "Yes" = 1 */
int items = WMGetPopUpButtonNumberOfItems(
panel->customPaletteHistoryBtn);
remove(toPath);
/* Remove from History list too */
index = 1;
while ((index < items) && (strcmp(WMGetPopUpButtonItem(
panel->customPaletteHistoryBtn, index),
toName) != 0 ))
index++;
if (index < items) {
WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn,
index);
if (index < item)
item--;
}
} else {
wfree(fromPath);
wfree(toName);
wfree(toPath);
return;
}
}
if ( rename(fromPath, toPath) != 0)
wsyserror("Couldn't rename palette %s to %s\n", fromName, toName);
else {
WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
WMInsertPopUpButtonItem(panel->customPaletteHistoryBtn, item,
toName);
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn, item);
}
wfree(fromPath);
wfree(toPath);
wfree(toName);
}
}
static void
customPaletteMenuRemove(W_ColorPanel *panel)
{
W_Screen *scr = WMWidgetScreen(panel->win);
char *text;
char *tmp;
int choice;
int item;
item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
tmp = wstrconcat( "This will permanently remove the palette ",
WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
text = wstrconcat( tmp,
".\n\nAre you sure you want to remove this palette ?");
wfree(tmp);
choice = WMRunAlertPanel(scr, panel->win, "Remove", text, "Yes", "No",
NULL);
/* returns 0 (= "Yes") or 1 (="No") */
wfree(text);
if (choice == 0) {
tmp = wstrconcat(panel->configurationPath,
WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item ));
if ( remove(tmp) == 0) {
/* item-1 always exists */
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
item-1);
customPaletteHistoryCallback(panel->customPaletteHistoryBtn,
panel);
customSetPalette(panel);
WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
} else {
wsyserror("Couldn't remove palette %s\n", tmp);
}
wfree(tmp);
}
}
static void
customPaletteHistoryCallback(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel*)data;
W_Screen *scr = WMWidgetScreen(panel->win);
int item;
char *filename;
RImage *tmp = NULL;
unsigned char perm_mask;
item = WMGetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn);
if (item == panel->currentPalette)
return;
if (item == 0) {
customRenderSpectrum(panel);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
False );
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
False );
} else {
/* Load file from configpath */
filename = wstrconcat( panel->configurationPath,
WMGetPopUpButtonItem(panel->customPaletteHistoryBtn, item) );
/* If the file corresponding to the item does not exist,
* remove it from the history list and select the next one.
*/
perm_mask = (access(filename, F_OK) == 0);
if (!perm_mask) {
/* File does not exist */
wfree(filename);
WMSetPopUpButtonSelectedItem(panel->customPaletteHistoryBtn,
item-1);
WMRemovePopUpButtonItem(panel->customPaletteHistoryBtn, item);
customPaletteHistoryCallback(w, data);
return;
}
/* Get the image */
tmp = RLoadImage(scr->rcontext, filename, 0);
if (tmp) {
if (panel->customPaletteImg) {
RReleaseImage(panel->customPaletteImg);
panel->customPaletteImg = NULL;
}
panel->customPaletteImg = tmp;
}
/* If the image is not writable, don't allow removing/renaming */
perm_mask = (access(filename, W_OK) == 0);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRename,
perm_mask);
WMSetPopUpButtonItemEnabled(panel->customPaletteMenuBtn, CPmenuRemove,
perm_mask);
wfree(filename);
}
customSetPalette(panel);
panel->currentPalette = item;
}
/************************* ColorList Panel Functions **********************/
static void
colorListPaintItem(WMList *lPtr, int index, Drawable d, char *text,
int state, WMRect *rect)
{
int width, height, x, y;
RColor color = *((RColor *)WMGetListItem(lPtr, index)->clientData);
WMScreen *scr = WMWidgetScreen(lPtr);
Display *dpy = WMScreenDisplay(scr);
W_ColorPanel *panel = WMGetHangedData(lPtr);
WMColor *white = WMWhiteColor(scr);
WMColor *black = WMBlackColor(scr);
WMColor *fillColor;
width = rect->size.width;
height = rect->size.height;
x = rect->pos.x;
y = rect->pos.y;
if (state & WLDSSelected)
WMPaintColorSwatch(white, d, x +15, y, width -15, height);
else
XClearArea(dpy, d, x +15, y, width -15, height, False);
fillColor = WMCreateRGBColor(scr, color.red*256, color.green*256,
color.blue*256, False);
WMSetColorInGC(fillColor, WMColorGC(fillColor));
WMPaintColorSwatch(fillColor, d, x, y, 15, 15);
WMReleaseColor(fillColor);
WMDrawString(scr, d, WMColorGC(black), panel->font12, x+18, y, text,
strlen(text));
WMReleaseColor(white);
WMReleaseColor(black);
}
static void
colorListSelect(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *)data;
CPColor cpColor;
cpColor.rgb = *((RColor *)WMGetListSelectedItem(w)->clientData);
cpColor.set = cpRGB;
panel->lastChanged = WMColorListModeColorPanel;
updateSwatch(panel, cpColor);
}
static void
colorListColorMenuCallback(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *)data;
int item = WMGetPopUpButtonSelectedItem(panel->colorListColorMenuBtn);
switch (item) {
case CLmenuAdd:
break;
case CLmenuRename:
break;
case CLmenuRemove:
break;
}
}
static void
colorListListMenuCallback(WMWidget *w, void *data)
{
W_ColorPanel *panel = (W_ColorPanel *)data;
int item = WMGetPopUpButtonSelectedItem(panel->colorListListMenuBtn);
switch (item) {
case CLmenuAdd:
/* New Color List */
colorListListMenuNew(panel);
break;
case CLmenuRename:
break;
case CLmenuRemove:
break;
}
}
static void
colorListListMenuNew(W_ColorPanel *panel)
{
}
/*************** Panel Initialisation Functions *****************/
static void
wheelInit(W_ColorPanel *panel)
{
CPColor cpColor;
if (panel->color.set != cpHSV)
convertCPColor(&panel->color);
WMSetSliderValue(panel->wheelBrightnessS, 255 - panel->color.hsv.value);
panel->colx = 2 + rint((colorWheelSize / 2.0) *
(1 + ( panel->color.hsv.saturation/255.0) *
cos( panel->color.hsv.hue * M_PI/180.0)));
panel->coly = 2 + rint((colorWheelSize / 2.0) *
(1 + ( panel->color.hsv.saturation/255.0) *
sin(- panel->color.hsv.hue*M_PI/180.0)));
wheelCalculateValues(panel, panel->color.hsv.value);
cpColor = panel->color;
cpColor.hsv.value = 255;
cpColor.set = cpHSV;
wheelUpdateBrightnessGradient(panel, cpColor);
}
static void
grayInit(W_ColorPanel *panel)
{
int value;
char tmp[4];
if (panel->color.set != cpHSV)
convertCPColor(&panel->color);
value = rint(panel->color.hsv.value/2.55);
WMSetSliderValue(panel->grayBrightnessS, value);
sprintf(tmp, "%d", value);
WMSetTextFieldText(panel->grayBrightnessT, tmp);
}
static void
rgbInit(W_ColorPanel *panel)
{
char tmp[4];
if (panel->color.set != cpRGB)
convertCPColor(&panel->color);
WMSetSliderValue(panel->rgbRedS, panel->color.rgb.red);
WMSetSliderValue(panel->rgbGreenS, panel->color.rgb.green);
WMSetSliderValue(panel->rgbBlueS, panel->color.rgb.blue);
sprintf(tmp, "%d", panel->color.rgb.red);
WMSetTextFieldText(panel->rgbRedT, tmp);
sprintf(tmp, "%d", panel->color.rgb.green);
WMSetTextFieldText(panel->rgbGreenT, tmp);
sprintf(tmp, "%d", panel->color.rgb.blue);
WMSetTextFieldText(panel->rgbBlueT, tmp);
}
static void
cmykInit(W_ColorPanel *panel)
{
int value[3];
char tmp[4];
if (panel->color.set != cpRGB)
convertCPColor(&panel->color);
value[0] = rint((255-panel->color.rgb.red)/2.55);
value[1] = rint((255-panel->color.rgb.green)/2.55);
value[2] = rint((255-panel->color.rgb.blue)/2.55);
WMSetSliderValue(panel->cmykCyanS, value[0]);
WMSetSliderValue(panel->cmykMagentaS, value[1]);
WMSetSliderValue(panel->cmykYellowS, value[2]);
WMSetSliderValue(panel->cmykBlackS, 0);
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->cmykCyanT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->cmykMagentaT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->cmykYellowT, tmp);
WMSetTextFieldText(panel->cmykBlackT, "0");
}
static void
hsbInit(W_ColorPanel *panel)
{
int value[3];
char tmp[4];
if (panel->color.set != cpHSV)
convertCPColor(&panel->color);
value[0] = panel->color.hsv.hue;
value[1] = rint(panel->color.hsv.saturation/2.55);
value[2] = rint(panel->color.hsv.value/2.55);
WMSetSliderValue(panel->hsbHueS,value[0]);
WMSetSliderValue(panel->hsbSaturationS,value[1]);
WMSetSliderValue(panel->hsbBrightnessS,value[2]);
sprintf(tmp, "%d", value[0]);
WMSetTextFieldText(panel->hsbHueT, tmp);
sprintf(tmp, "%d", value[1]);
WMSetTextFieldText(panel->hsbSaturationT, tmp);
sprintf(tmp, "%d", value[2]);
WMSetTextFieldText(panel->hsbBrightnessT, tmp);
hsbUpdateBrightnessGradient(panel);
hsbUpdateSaturationGradient(panel);
hsbUpdateHueGradient(panel);
}
/************************** Common utility functions ************************/
static int
fetchFile(char *toPath, char *srcFile, char *destFile)
{
int src, dest;
int n;
char *tmp;
char buf[BUFSIZE];
if ((src = open(srcFile, O_RDONLY)) == 0) {
wsyserror("Could not open %s", srcFile);
return -1;
}
tmp = wstrconcat(toPath, destFile);
if ((dest = open( tmp, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))
== 0) {
wsyserror("Could not create %s", tmp);
wfree(tmp);
return -1;
}
wfree(tmp);
/* Copy the file */
while ((n = read(src, buf, BUFSIZE)) > 0)
{
if (write (dest, buf, n) != n) {
wsyserror("Write error on file %s", destFile);
return -1;
}
}
return 0;
}
char*
generateNewFilename(char *curName)
{
int n;
char c;
int baseLen;
char *ptr;
char *newName;
assert(curName);
ptr = curName;
if (((ptr = strrchr(ptr, '{'))==0) || sscanf(ptr, "{%i}%c", &n, &c)!=1)
return wstrconcat(curName, " {1}");
baseLen = ptr - curName -1;
newName = wmalloc(baseLen + 16);
strncpy(newName, curName, baseLen);
newName[baseLen] = 0;
sprintf(&newName[baseLen], " {%i}", n+1);
return newName;
}
void
convertCPColor(CPColor *color)
{
unsigned short old_hue = 0;
switch (color->set) {
case cpNone:
wwarning("Color Panel: Color unspecified");
return;
case cpRGB:
old_hue = color->hsv.hue;
RRGBtoHSV(&(color->rgb), &(color->hsv));
/* In black the hue is undefined, and may change by conversion
* Same for white. */
if (
((color->rgb.red == 0) &&
(color->rgb.green == 0) &&
(color->rgb.blue == 0)) ||
((color->rgb.red == 0) &&
(color->rgb.green == 0) &&
(color->rgb.blue == 255))
)
color->hsv.hue = old_hue;
break;
case cpHSV:
RHSVtoRGB(&(color->hsv), &(color->rgb));
break;
}
}
#define ABS_SHIFT(val, shift) \
(((shift) > 0) ? (val) >> (shift) : (val) << -(shift))
RColor
ulongToRColor(WMScreen *scr, unsigned long value)
{
RColor color;
XColor *xcolor = NULL;
if (!(xcolor = wmalloc(sizeof(XColor)) )) {
wwarning(NO_MEMORY_ERR);
color.red = 0;
color.green = 0;
color.blue = 0;
return color;
}
xcolor->pixel = value;
XQueryColor(scr->display, scr->rcontext->cmap, xcolor);
color.red = xcolor->red >> 8;
color.green = xcolor->green >> 8;
color.blue = xcolor->blue >> 8;
wfree(xcolor);
return color;
}
unsigned char
getShift(unsigned char value)
{
unsigned char i = -1;
if (value == 0)
return 0;
while (value) {
value >>= 1;
i++;
}
return i;
}
#ifdef SHAPE_WAS_DEFINED
#undef SHAPE_WAS_DEFINED
#define SHAPE
#endif