mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-28 09:22:27 +01:00
---------------
- 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.
3795 lines
112 KiB
C
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
|