#include "ET++.ph" #ifdef __GNUG__ #pragma implementation #endif #include "ColorPicker.h" #include "Class.h" #include "ScrollBar.h" #include "Slider.h" #include "WindowPort.h" #include "Window.h" #include "Buttons.h" #include "Filler.h" #include "Look.h" #include "BorderItems.h" #include "Fields.h" #include "Math.h" #include "PopupItem.h" #include "OrdColl.h" #include "CollView.h" #include "Menu.h" enum { cCpValAlphaSlider, cCpRGBSlider, cCpPicker, cCpWheel, cCpReset, cCpHueSatNum, cCpSlider, cCpNumField, cCpPopup, cCpCancel, cCpSetColor }; IdRange ColorPickerRange(cCpSetColor+1); static ColorPicker *gPicker; ONEXIT(ColorPicker) { SafeDelete(gPicker); } //---- ColorCell --------------------------------------------------------------- class ColorCell: public VObject { RGBColor *rc; public: MetaDef(ColorCell); ColorCell(RGB c, Point e, bool hfix= TRUE); ColorCell(RGBColor *c, Point e, bool hfix= TRUE); ~ColorCell(); void DrawAll(Rectangle r, bool highlight); void SetColor(RGB c); RGB GetColor() { return *rc->GetRGB(); } }; //---- ColorCell --------------------------------------------------------------- NewMetaImpl(ColorCell,VObject, (TP(rc))); ColorCell::~ColorCell() { SafeDelete(rc); } void ColorCell::SetColor(RGB c) { RGBColor *rr= (RGBColor*) gLook->GetBackgroundColor(); RGB d, b(*rr->GetRGB()); d.red= (b.red*(255-c.alpha) + c.red*c.alpha)/255; d.green= (b.green*(255-c.alpha) + c.green*c.alpha)/255; d.blue= (b.blue*(255-c.alpha) + c.blue*c.alpha)/255; if (rc->SetRGB(&d, MaxWord)) ForceRedraw(); } ColorCell::ColorCell(RGB c, Point e, bool hfix) : VObject(e) { rc= new RGBColor(c); rc->SetPrec(MaxWord); SetFlag(eVObjVFixed); SetFlag(eVObjHFixed, hfix); } ColorCell::ColorCell(RGBColor *c, Point e, bool hfix) : VObject(e) { rc= c; rc->SetPrec(MaxWord); SetFlag(eVObjVFixed); SetFlag(eVObjHFixed, hfix); } void ColorCell::DrawAll(Rectangle r, bool highlight) { if (IsOpen() && r.Clip(contentRect)) { if (highlight || TestFlag(eVObjHighlight)) { GrPaintRect(r, gHighlightColor); GrPaintRect(contentRect.Inset(2), rc); } else GrPaintRect(contentRect, rc); } } //---- CPicker ----------------------------------------------------------------- class CPicker: public Box { public: MetaDef(CPicker); CPicker() : Box(ColorPickerRange()+cCpPicker, gPoint1, gPoint0, (VObjAlign)(eVObjHExpand+eVObjVExpand)) { } virtual void SetColor(RGB, bool) { } virtual RGB GetColor() { return RGB(0,0,0); } virtual VObject *DoMakeContent() { return 0; } void SetContainer(VObject *v); }; NewMetaImpl0(CPicker,Box); void CPicker::SetContainer(VObject *v) { if (Size() <= 0) Add(new BorderItem(AsString(), DoMakeContent())); Box::SetContainer(v); } //---- ColorSlider ------------------------------------------------------------- class ColorSlider : public VBox { IntField *num; Slider *slider; public: ColorSlider(int id, char *label); void SetVal(int val, bool redraw); void Control(int id, int part, void *val); int GetVal() { return slider->GetMax().y-slider->GetVal().y; } }; ColorSlider::ColorSlider(int id, char *label) : VBox(gPoint5, (VObjAlign)(eVObjHCenter+eVObjVExpand)) { SetId(id); slider= new Slider(cCpSlider+ColorPickerRange(), eVert, TRUE); slider->SetMax(255, FALSE); Add(slider); num= new IntField(cCpNumField+ColorPickerRange(), 0, 0, 255); Add(new HBox(5, eVObjVBase, new TextItem(label), num, 0)); } void ColorSlider::SetVal(int val, bool redraw) { slider->SetVal(slider->GetMax().y-val, redraw); num->SetValue(val, redraw); } void ColorSlider::Control(int id, int part, void *val) { switch (id-ColorPickerRange()) { case cCpSlider: if (part == eSliderThumb) { num->SetValue(slider->GetMax().y-slider->GetVal().y, TRUE); Control(GetId(), eSliderThumb, 0); } break; case cCpNumField: if (part == cPartValueChanged) { slider->SetVal(slider->GetMax().y-num->GetValue(), TRUE); Control(GetId(), eSliderThumb, 0); } break; default: VBox::Control(id, part, val); break; } } //---- ColorWheel -------------------------------------------------------------- static short StdSectors[] = { 36, 36, 18, 18, 1, 0 }; class ColorWheel: public VObject { protected: short *sectors; int circles, maxix, sz; HSVColor hsv; RGBColor *palette; Point border; ImageCache cache; public: MetaDef(ColorWheel); ColorWheel(int id, short *sectors= StdSectors); ~ColorWheel(); void Draw(Rectangle cr); Command *DoLeftButtonDownCommand(Point, Token, int); void SetColor(HSVColor c, bool redraw); void SetColor2(HSVColor c, bool redraw); Rectangle DotRect(); HSVColor MapPointToColor(Point p); Metric GetMinSize() { return Metric(245); } HSVColor GetColor() { return hsv; } }; //---- PickerCommand ----------------------------------------------------------- class PickerCommand: public Command { ColorWheel *wheel; public: PickerCommand(class ColorWheel *w) : Command("pick") { wheel= w; } Command *TrackMouse(TrackPhase, Point ap, Point, Point np); void TrackFeedback(Point, Point, bool) { } }; Command *PickerCommand::TrackMouse(TrackPhase atp, Point, Point, Point np) { wheel->SetColor2(wheel->MapPointToColor(np), TRUE); if (atp == eTrackRelease) return gNoChanges; return this; } //---- ColorWheel -------------------------------------------------------------- NewMetaImpl(ColorWheel,VObject, (TV(sectors,circles), T(circles), T(maxix), T(border))); ColorWheel::ColorWheel(int id, short *sects) : VObject(id) { sectors= sects; for (sz= circles= 0; sectors[circles]; circles++) sz+= sectors[circles]; border= 6; palette= new RGBColor[sz]; maxix= 0; SetColor(HSVColor(0, MaxWord, MaxWord), FALSE); SetFlag(eVObjHFixed|eVObjVFixed); } ColorWheel::~ColorWheel() { SafeDelete(palette); } HSVColor ColorWheel::MapPointToColor(Point p) { HSVColor hc= hsv; double rad= contentRect.Inset(border).extent.x / 2.0; hc.hue= contentRect.PointToAngle(p); hc.saturation= (int) (Length(p - contentRect.Center()) / rad * (double)MaxWord + 0.5); return hc; } Rectangle ColorWheel::DotRect() { Rectangle mark(13), inner= contentRect.Inset(border); double w= (double) inner.extent.x / (double) MaxWord * hsv.saturation / 2.0, h= (double) inner.extent.y / (double) MaxWord * hsv.saturation / 2.0; mark.origin= contentRect.Center() + PolarToPoint((double)(hsv.hue), w, h) - mark.extent/2; return mark; } void ColorWheel::SetColor(HSVColor c, bool redraw) { if (hsv.hue != c.hue || hsv.saturation != c.saturation) { if (redraw) InvalidateRect(DotRect()); hsv.hue= c.hue; hsv.saturation= Math::Min(c.saturation, (short) MaxWord); if (redraw) InvalidateRect(DotRect()); } if (c.value != hsv.value || c.alpha != hsv.alpha) { int i, cir; bool invalidate= FALSE; RGBColor *rr= (RGBColor*) gLook->GetBackgroundColor(); RGB b(*rr->GetRGB()); hsv.value= c.value; hsv.alpha= c.alpha; for (i= cir= 0; cir < circles; cir++) { int sat= (MaxWord * (circles-1-cir)) / circles; for (int h= 0; h < sectors[cir]; h++) { int hue= (360 * h + (360/sectors[cir]/2)) / sectors[cir]; HSVColor h(hue, sat, c.value); RGB d(h); d.red= (b.red*(255-c.alpha) + d.red*c.alpha)/255; d.green= (b.green*(255-c.alpha) + d.green*c.alpha)/255; d.blue= (b.blue*(255-c.alpha) + d.blue*c.alpha)/255; if (palette[i].SetRGB(&d, MaxWord)) invalidate= TRUE; i++; } } if (invalidate) { ForceRedraw(); cache.Invalidate(); } } } void ColorWheel::SetColor2(HSVColor c, bool redraw) { if (hsv.hue != c.hue || hsv.saturation != c.saturation) { SetColor(c, redraw); Control(GetId(), cPartValueChanged, (void*) &hsv); } } void ColorWheel::Draw(Rectangle) { //if (cache.Open(cr)) { Rectangle r(contentRect.Inset(border)); Point Step= r.extent/(2*circles-1); int sat, i; for (i= sat= 0; sat < circles; sat++) { for (int hue= 0; hue < sectors[sat]; hue++) GrPaintWedge(r, 360 * hue / sectors[sat], 360/sectors[sat], &palette[i++]); r= r.Inset(Step); } GrSetPenNormal(); GrSetPenSize(2); GrStrokeOval(contentRect.Inset(border)); //cache.Close(); //} GrSetPenSize(3); GrSetPenInk(gInkWhite); GrStrokeOval(DotRect()); GrSetPenNormal(); GrSetPenInk(gInkBlack); GrStrokeOval(DotRect().Inset(1)); } Command *ColorWheel::DoLeftButtonDownCommand(Point, Token, int) { return new PickerCommand(this); } //---- HSVPicker --------------------------------------------------------------- class HSVPicker: public CPicker { ColorSlider *valslider, *alpha; ColorWheel *wheel; IntField *hNum, *sNum; public: MetaDef(HSVPicker); HSVPicker() : CPicker() { } void SetColor(RGB, bool); void Control(int id, int part, void *val); RGB GetColor(); const char *AsString() { return "HSVA"; } VObject *DoMakeContent(); }; NewMetaImpl(HSVPicker,CPicker, (TP(valslider), TP(alpha), TP(wheel), TP(hNum), TP(sNum))); VObject *HSVPicker::DoMakeContent() { wheel= new ColorWheel(cCpWheel+ColorPickerRange()); valslider= new ColorSlider(cCpValAlphaSlider+ColorPickerRange(), "V:"); alpha= new ColorSlider(cCpValAlphaSlider+ColorPickerRange(), "A:"); hNum= new IntField(cCpHueSatNum+ColorPickerRange(), 0, 0, 359); sNum= new IntField(cCpHueSatNum+ColorPickerRange(), 0, 0, 255); return new Expander(cCpPicker+ColorPickerRange(), eHor, Point(20), new VBox(5, eVObjVGapExpand, wheel, new HBox(10, (VObjAlign)(eVObjVBase+eVObjHGapExpand), new HBox(5, eVObjVBase, new TextItem("Hue:"), hNum, 0), new HBox(5, eVObjVBase, new TextItem("Saturation:"), sNum, 0), 0 ), 0 ), valslider, alpha, 0 ); } RGB HSVPicker::GetColor() { return HSVColor(hNum->GetValue(), sNum->GetValue(), valslider->GetVal(), alpha->GetVal()); } void HSVPicker::SetColor(RGB c, bool redraw) { HSVColor hsv(c); wheel->SetColor(hsv, redraw); hNum->SetValue(hsv.hue, redraw); sNum->SetValue(hsv.saturation, redraw); valslider->SetVal(hsv.value, redraw); alpha->SetVal(hsv.alpha, redraw); } void HSVPicker::Control(int id, int part, void *val) { switch (id-ColorPickerRange()) { case cCpHueSatNum: if (part == cPartValueChanged) { HSVColor color(hNum->GetValue(), sNum->GetValue(), valslider->GetVal(), alpha->GetVal()); wheel->SetColor(color, TRUE); Control(cCpPicker+ColorPickerRange(), cPartValueChanged, 0); } break; case cCpValAlphaSlider: if (part == eSliderThumb) { HSVColor color(hNum->GetValue(), sNum->GetValue(), valslider->GetVal(), alpha->GetVal()); wheel->SetColor(color, TRUE); Control(cCpPicker+ColorPickerRange(), cPartValueChanged, 0); } break; case cCpWheel: if (part == cPartValueChanged) { HSVColor color(wheel->GetColor()); hNum->SetValue(color.hue, TRUE); sNum->SetValue(color.saturation, TRUE); Control(cCpPicker+ColorPickerRange(), cPartValueChanged, 0); } break; default: CPicker::Control(id, part, val); break; } } //---- RGBPicker --------------------------------------------------------------- class RGBPicker: public CPicker { ColorSlider *red, *green, *blue, *alpha; public: MetaDef(RGBPicker); RGBPicker() : CPicker() { } void SetColor(RGB, bool redraw); void Control(int id, int part, void *val); RGB GetColor() { return RGB(red->GetVal(), green->GetVal(), blue->GetVal(), alpha->GetVal()); } const char *AsString() { return "RGBA"; } VObject *DoMakeContent(); }; NewMetaImpl(RGBPicker,CPicker, (TP(red), TP(green), TP(blue), TP(alpha))); VObject *RGBPicker::DoMakeContent() { return new Expander(cCpPicker+ColorPickerRange(), eHor, Point(20), red= new ColorSlider(cCpRGBSlider+ColorPickerRange(), "R:"), green= new ColorSlider(cCpRGBSlider+ColorPickerRange(), "G:"), blue= new ColorSlider(cCpRGBSlider+ColorPickerRange(), "B:"), alpha= new ColorSlider(cCpRGBSlider+ColorPickerRange(), "A:"), 0 ); } void RGBPicker::Control(int id, int part, void *val) { if (id == cCpRGBSlider-ColorPickerRange() && part == eSliderThumb) CPicker::Control(cCpPicker+ColorPickerRange(), cPartValueChanged, 0); else CPicker::Control(id, part, val); } void RGBPicker::SetColor(RGB color, bool redraw) { red->SetVal(color.red, redraw); green->SetVal(color.green, redraw); blue->SetVal(color.blue, redraw); alpha->SetVal(color.alpha, redraw); } //---- PalettePicker ----------------------------------------------------------- class PalettePicker: public CPicker { CollectionView *cv; RGB c; public: MetaDef(PalettePicker); PalettePicker() : CPicker() { } RGB GetColor(); void SetColor(RGB cc, bool) { c= cc; } VObject *DoMakeContent(); const char *AsString() { return "Palette"; } void Control(int id, int part, void *val); }; NewMetaImpl0(PalettePicker,CPicker); VObject *PalettePicker::DoMakeContent() { OrdCollection *col= new OrdCollection; for (int i= 0; i < 256; i++) col->Add(new ColorCell(new RGBColorCell(i), Point(15))); cv= new CollectionView(this, col, eCVDefault, 16, 16); cv->SetId(cCpPicker+ColorPickerRange()); cv->SetGap(gPoint1); return cv; } RGB PalettePicker::GetColor() { Rectangle s(cv->GetSelection()); ColorCell *cc= (ColorCell*) cv->GetItem(s.origin.x, s.origin.y); if (cc) return cc->GetColor(); return c; } void PalettePicker::Control(int id, int part, void *val) { if (part == cPartCollSelect) CPicker::Control(cCpPicker+ColorPickerRange(), cPartValueChanged, 0); else CPicker::Control(id, part, val); } //---- ColorPicker ------------------------------------------------------------- NewMetaImpl(ColorPicker,Dialog, (TP(oldcell), TP(newcell))); ColorPicker::ColorPicker(char *name) : Dialog(name) { current= 0; pickers= new OrdCollection; pickers->Add(new PalettePicker); pickers->Add(new HSVPicker); pickers->Add(new RGBPicker); } void ColorPicker::DoSetup() { //newcell->SetColor(color); //oldcell->SetColor(oldcolor); } void ColorPicker::DoSetDefaults() { //newcell->SetColor(color); //oldcell->SetColor(oldcolor); } VObject *ColorPicker::DoMakeContent() { Iter next(pickers); CPicker *p; Menu *m= new Menu("Model", FALSE); for (int id= 0; p= (CPicker*) next(); id++) m->AppendItem(p->AsString(), id); RGB rc(color); return new Matte( new HExpander(gPoint10, border= new VExpander(gPoint10, (CPicker*)pickers->At(current), 0 ), new VExpander(gPoint10, new BorderItem("Old/New", new VBox(gPoint0, (VObjAlign)(eVObjHExpand), oldcell= new ColorCell(rc, Point(75, 45), FALSE), newcell= new ColorCell(rc, Point(75, 45), FALSE), 0 ) ), new Filler(gPoint10), new PopupButton(cCpPopup+ColorPickerRange(), current, m), new Filler(gPoint10), new ActionButton(cCpReset+ColorPickerRange(), "Reset"), new ActionButton(cCpCancel+ColorPickerRange(), "Cancel"), new ActionButton(cIdYes+ColorPickerRange(), "Set Color", TRUE), 0 ), 0 ) ); } void ColorPicker::Control(int id, int part, void *val) { CPicker *picker; switch (id-ColorPickerRange()) { case cCpPopup: if (part == cPartToggle && current != (int)val) { SetFirstHandler(0); current= (int)val; picker= (CPicker*) pickers->At(current); if (picker) { border->SetAt(0, picker); picker->SetColor(color, FALSE); } } break; case cCpPicker: if (part == cPartValueChanged) { picker= (CPicker*) pickers->At(current); color= picker->GetColor(); newcell->SetColor(color); } break; case cCpSetColor: newcell->SetColor(*((RGB*)val)); break; case cCpReset: color= oldcolor; picker= (CPicker*) pickers->At(current); picker->SetColor(color, TRUE); newcell->SetColor(color); id= cIdNone; break; case cCpCancel: color= oldcolor; id= cIdCancel; break; } Dialog::Control(id, part, val); } RGB ColorPicker::PickColor(const RGB &c) { color= c; oldcolor= c; Dialog::ShowUnderMouse(); return color; } RGB PickColor(const RGB &c) { if (gPicker == 0) gPicker= new ColorPicker("Color Picker"); return gPicker->PickColor(c); }