From 31e20891067fdd01ab68bc891566f070ff73ef58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Fri, 23 Jun 2006 22:09:53 +0000 Subject: [PATCH] * added a color picker panel (heavily modified, but originally based on Colors! by Werner Freytag) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17915 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/icon-o-matic/CanvasView.cpp | 1 + src/apps/icon-o-matic/IconEditorApp.cpp | 8 + src/apps/icon-o-matic/Jamfile | 9 + .../gui/panel/color_picker/ColorField.cpp | 627 ++++++++++++++++ .../gui/panel/color_picker/ColorField.h | 93 +++ .../gui/panel/color_picker/ColorPickerDefs.h | 6 + .../panel/color_picker/ColorPickerPanel.cpp | 164 +++++ .../gui/panel/color_picker/ColorPickerPanel.h | 40 ++ .../panel/color_picker/ColorPickerView.cpp | 504 +++++++++++++ .../gui/panel/color_picker/ColorPickerView.h | 94 +++ .../gui/panel/color_picker/ColorPreview.cpp | 211 ++++++ .../gui/panel/color_picker/ColorPreview.h | 57 ++ .../gui/panel/color_picker/ColorSlider.cpp | 669 ++++++++++++++++++ .../gui/panel/color_picker/ColorSlider.h | 98 +++ .../generic/gui/panel/color_picker/LICENSE | 16 + .../generic/gui/panel/color_picker/rgb_hsv.h | 94 +++ .../panel/color_picker/selected_color_mode.h | 18 + .../generic/support/support_ui.cpp | 18 +- .../icon-o-matic/generic/support/support_ui.h | 4 - 19 files changed, 2710 insertions(+), 21 deletions(-) create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorField.cpp create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorField.h create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerDefs.h create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerPanel.cpp create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerPanel.h create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerView.cpp create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerView.h create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPreview.cpp create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPreview.h create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorSlider.cpp create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorSlider.h create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/LICENSE create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/rgb_hsv.h create mode 100644 src/apps/icon-o-matic/generic/gui/panel/color_picker/selected_color_mode.h diff --git a/src/apps/icon-o-matic/CanvasView.cpp b/src/apps/icon-o-matic/CanvasView.cpp index 18e7e59cf5..3fbd2e1fa5 100644 --- a/src/apps/icon-o-matic/CanvasView.cpp +++ b/src/apps/icon-o-matic/CanvasView.cpp @@ -242,6 +242,7 @@ CanvasView::_AllocBackBitmap(float width, float height) fOffsreenView->SetFont(&font); fOffsreenView->SetHighColor(HighColor()); fOffsreenView->SetLowColor(LowColor()); + fOffsreenView->SetFlags(Flags()); fOffsreenBitmap->AddChild(fOffsreenView); } else { _FreeBackBitmap(); diff --git a/src/apps/icon-o-matic/IconEditorApp.cpp b/src/apps/icon-o-matic/IconEditorApp.cpp index 548f8049a3..214889d0dc 100644 --- a/src/apps/icon-o-matic/IconEditorApp.cpp +++ b/src/apps/icon-o-matic/IconEditorApp.cpp @@ -15,6 +15,9 @@ #include "Document.h" #include "MainWindow.h" +// testing: +#include "ColorPickerPanel.h" + using std::nothrow; // constructor @@ -68,6 +71,11 @@ IconEditorApp::ReadyToRun() { fMainWindow = new MainWindow(this, fDocument); fMainWindow->Show(); + + ColorPickerPanel* panel = new ColorPickerPanel( + BRect(80, 80, 200, 200), + (rgb_color){ 100, 200, 150, 255 }); + panel->Show(); } diff --git a/src/apps/icon-o-matic/Jamfile b/src/apps/icon-o-matic/Jamfile index 926c8d2ec1..72b1850ff5 100644 --- a/src/apps/icon-o-matic/Jamfile +++ b/src/apps/icon-o-matic/Jamfile @@ -10,6 +10,7 @@ local sourceDirs = generic/command generic/gui generic/gui/panel + generic/gui/panel/color_picker generic/gui/popup_control generic/gui/scrollview generic/gui/stateview @@ -43,6 +44,13 @@ Application Icon-O-Matic : Selection.cpp # generic/gui # generic/gui/panel + Panel.cpp + # generic/gui/panel/color_picker + ColorField.cpp + ColorPickerPanel.cpp + ColorPickerView.cpp + ColorPreview.cpp + ColorSlider.cpp # generic/gui/popup_control # generic/gui/scrollview # generic/gui/stateview @@ -57,6 +65,7 @@ Application Icon-O-Matic : # generic/support RWLocker.cpp support.cpp + support_ui.cpp # gradient Gradient.cpp # shape diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorField.cpp b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorField.cpp new file mode 100644 index 0000000000..ceb4941af2 --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorField.cpp @@ -0,0 +1,627 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. + * + */ + +#include "ColorField.h" + +#include + +#include +#include +#include +#include + +#include "selected_color_mode.h" +#include "support_ui.h" + +#include "rgb_hsv.h" + +#define round(x) (int)(x+.5) + +enum { + MSG_UPDATE = 'Updt', +}; + +#define MAX_X 255 +#define MAX_Y 255 + +// constructor +ColorField::ColorField(BPoint offset_point, selected_color_mode mode, + float fixed_value, orientation orient) + : BControl(BRect(0.0, 0.0, MAX_X + 4.0, MAX_Y + 4.0).OffsetToCopy(offset_point), + "ColorField", "", new BMessage(MSG_COLOR_FIELD), + B_FOLLOW_LEFT | B_FOLLOW_TOP, + B_WILL_DRAW | B_FRAME_EVENTS), + fMode(mode), + fFixedValue(fixed_value), + fOrientation(orient), + fMarkerPosition(0.0, 0.0), + fLastMarkerPosition(-1.0, -1.0), + fMouseDown(false), + fUpdateThread(B_ERROR), + fUpdatePort(B_ERROR) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + + for (int i = 0; i < 2; ++i) { + fBgBitmap[i] = new BBitmap(Bounds(), B_RGB32, true); + + fBgBitmap[i]->Lock(); + fBgView[i] = new BView(Bounds(), "", B_FOLLOW_NONE, B_WILL_DRAW); + fBgBitmap[i]->AddChild(fBgView[i]); + fBgView[i]->SetOrigin(2.0, 2.0); + fBgBitmap[i]->Unlock(); + } + + _DrawBorder(); + + fUpdatePort = create_port(100, "color field update port"); + + fUpdateThread = spawn_thread(ColorField::_UpdateThread, + "color field update thread", 10, this); + resume_thread(fUpdateThread); + +// Update(3); +} + +// destructor +ColorField::~ColorField() +{ + if (fUpdatePort >= B_OK) + delete_port(fUpdatePort); + if (fUpdateThread >= B_OK) + kill_thread(fUpdateThread); + + delete fBgBitmap[0]; + delete fBgBitmap[1]; +} + +#if LIB_LAYOUT +// layoutprefs +minimax +ColorField::layoutprefs() +{ + if (fOrientation == B_VERTICAL) { + mpm.mini.x = 4 + MAX_X / 17; + mpm.mini.y = 4 + MAX_Y / 5; + } else { + mpm.mini.x = 4 + MAX_X / 5; + mpm.mini.y = 4 + MAX_Y / 17; + } + mpm.maxi.x = 4 + MAX_X; + mpm.maxi.y = 4 + MAX_Y; + + mpm.weight = 1.0; + + return mpm; +} + +// layout +BRect +ColorField::layout(BRect frame) +{ + MoveTo(frame.LeftTop()); + + // reposition marker + fMarkerPosition.x *= (frame.Width() - 4.0) / (Bounds().Width() - 4.0); + fMarkerPosition.y *= (frame.Height() - 4.0) / (Bounds().Height() - 4.0); + + ResizeTo(frame.Width(), frame.Height()); + _DrawBorder(); + Update(3); + return Frame(); +} +#endif // LIB_LAYOUT + +// Invoke +status_t +ColorField::Invoke(BMessage *msg) +{ + if (!msg) + msg = Message(); + + msg->RemoveName("value"); + + float v1 = 0; + float v2 = 0; + + switch (fMode) { + case R_SELECTED: + case G_SELECTED: + case B_SELECTED: + v1 = fMarkerPosition.x / Width(); + v2 = 1.0 - fMarkerPosition.y / Height(); + break; + + case H_SELECTED: + if (fOrientation == B_VERTICAL) { + v1 = fMarkerPosition.x / Width(); + v2 = 1.0 - fMarkerPosition.y / Height(); + } else { + v1 = fMarkerPosition.y / Height(); + v2 = 1.0 - fMarkerPosition.x / Width(); + } + break; + + case S_SELECTED: + case V_SELECTED: + v1 = fMarkerPosition.x / Width() * 6.0; + v2 = 1.0 - fMarkerPosition.y / Height(); + break; + + } + + msg->AddFloat("value", v1); + msg->AddFloat("value", v2); + + return BControl::Invoke(msg); +} + +// AttachedToWindow +void +ColorField::AttachedToWindow() +{ + Update(3); +} + +// Draw +void +ColorField::Draw(BRect updateRect) +{ + Update(0); +} + +// MouseDown +void +ColorField::MouseDown(BPoint where) +{ + Window()->Activate(); + + fMouseDown = true; + SetMouseEventMask(B_POINTER_EVENTS, B_SUSPEND_VIEW_FOCUS|B_LOCK_WINDOW_FOCUS ); + PositionMarkerAt( where ); + + if (Message()) { + BMessage message(*Message()); + message.AddBool("begin", true); + Invoke(&message); + } else + Invoke(); +} + +// MouseUp +void +ColorField::MouseUp(BPoint where) +{ + fMouseDown = false; +} + +// MouseMoved +void +ColorField::MouseMoved(BPoint where, uint32 code, const BMessage *a_message) +{ + if (a_message || !fMouseDown ) { + BView::MouseMoved( where, code, a_message); + return; + } + + PositionMarkerAt(where); + Invoke(); +} + +// Update +void +ColorField::Update(int depth) +{ + // depth: 0 = only onscreen redraw, 1 = only cursor 1, 2 = full update part 2, 3 = full + + if (depth == 3) { + write_port(fUpdatePort, MSG_UPDATE, NULL, 0); + return; + } + + if (depth >= 1) { + fBgBitmap[1]->Lock(); + + fBgView[1]->DrawBitmap( fBgBitmap[0], BPoint(-2.0, -2.0) ); + + fBgView[1]->SetHighColor( 0, 0, 0 ); + fBgView[1]->StrokeEllipse( fMarkerPosition, 5.0, 5.0 ); + fBgView[1]->SetHighColor( 255.0, 255.0, 255.0 ); + fBgView[1]->StrokeEllipse( fMarkerPosition, 4.0, 4.0 ); + + fBgView[1]->Sync(); + + fBgBitmap[1]->Unlock(); + } + + if (depth != 0 && depth != 2 && fMarkerPosition != fLastMarkerPosition) { + + fBgBitmap[1]->Lock(); + + DrawBitmap( fBgBitmap[1], + BRect(-3.0, -3.0, 7.0, 7.0).OffsetByCopy(fMarkerPosition), + BRect(-3.0, -3.0, 7.0, 7.0).OffsetByCopy(fMarkerPosition)); + DrawBitmap( fBgBitmap[1], + BRect(-3.0, -3.0, 7.0, 7.0).OffsetByCopy(fLastMarkerPosition), + BRect(-3.0, -3.0, 7.0, 7.0).OffsetByCopy(fLastMarkerPosition)); + + fLastMarkerPosition = fMarkerPosition; + + fBgBitmap[1]->Unlock(); + + } else + DrawBitmap(fBgBitmap[1]); + +} + +// SetModeAndValue +void +ColorField::SetModeAndValue(selected_color_mode mode, float fixed_value) +{ + float R(0), G(0), B(0); + float H(0), S(0), V(0); + + fBgBitmap[0]->Lock(); + + float width = Width(); + float height = Height(); + + switch (fMode) { + + case R_SELECTED: { + R = fFixedValue * 255; + G = round(fMarkerPosition.x / width * 255.0); + B = round(255.0 - fMarkerPosition.y / height * 255.0); + }; break; + + case G_SELECTED: { + R = round(fMarkerPosition.x / width * 255.0); + G = fFixedValue * 255; + B = round(255.0 - fMarkerPosition.y / height * 255.0); + }; break; + + case B_SELECTED: { + R = round(fMarkerPosition.x / width * 255.0); + G = round(255.0 - fMarkerPosition.y / height * 255.0); + B = fFixedValue * 255; + }; break; + + case H_SELECTED: { + H = fFixedValue; + S = fMarkerPosition.x / width; + V = 1.0 - fMarkerPosition.y / height; + }; break; + + case S_SELECTED: { + H = fMarkerPosition.x / width * 6.0; + S = fFixedValue; + V = 1.0 - fMarkerPosition.y / height; + }; break; + + case V_SELECTED: { + H = fMarkerPosition.x / width * 6.0; + S = 1.0 - fMarkerPosition.y / height; + V = fFixedValue; + }; break; + } + + if (fMode & (H_SELECTED | S_SELECTED | V_SELECTED)) { + HSV_to_RGB(H, S, V, R, G, B); + R *= 255.0; G *= 255.0; B *= 255.0; + } + + rgb_color color = { round(R), round(G), round(B), 255 }; + + fBgBitmap[0]->Unlock(); + + if (fFixedValue != fixed_value || fMode != mode) { + fFixedValue = fixed_value; + fMode = mode; + + Update(3); + } + + SetMarkerToColor(color); +} + +// SetFixedValue +void +ColorField::SetFixedValue(float fixed_value) +{ + if (fFixedValue != fixed_value) { + fFixedValue = fixed_value; + Update(3); + } +} + +// SetMarkerToColor +void +ColorField::SetMarkerToColor(rgb_color color) +{ + float h, s, v; + RGB_to_HSV( (float)color.red / 255.0, (float)color.green / 255.0, (float)color.blue / 255.0, h, s, v ); + + fLastMarkerPosition = fMarkerPosition; + + float width = Width(); + float height = Height(); + + switch (fMode) { + case R_SELECTED: { + fMarkerPosition = BPoint(color.green / 255.0 * width, + (255.0 - color.blue) / 255.0 * height); + } break; + + case G_SELECTED: { + fMarkerPosition = BPoint(color.red / 255.0 * width, + (255.0 - color.blue) / 255.0 * height); + } break; + + case B_SELECTED: { + fMarkerPosition = BPoint(color.red / 255.0 * width, + (255.0 - color.green) / 255.0 * height); + } break; + + case H_SELECTED: { + if (fOrientation == B_VERTICAL) + fMarkerPosition = BPoint(s * width, height - v * height); + else + fMarkerPosition = BPoint(width - v * width, s * height); + } break; + + case S_SELECTED: { + fMarkerPosition = BPoint(h / 6.0 * width, height - v * height); + } break; + + case V_SELECTED: { + fMarkerPosition = BPoint( h / 6.0 * width, height - s * height); + } break; + } + + Update(1); +} + +// PositionMarkerAt +void +ColorField::PositionMarkerAt( BPoint where ) +{ + BRect rect = Bounds().InsetByCopy( 2.0, 2.0 ).OffsetToCopy(0.0, 0.0); + where = BPoint(max_c(min_c(where.x - 2.0, rect.right), 0.0), + max_c(min_c(where.y - 2.0, rect.bottom), 0.0) ); + + fLastMarkerPosition = fMarkerPosition; + fMarkerPosition = where; + Update(1); + +} + +// Width +float +ColorField::Width() const +{ + return Bounds().IntegerWidth() + 1 - 4; +} + +// Height +float +ColorField::Height() const +{ + return Bounds().IntegerHeight() + 1 - 4; +} + +// set_bits +void +set_bits(uint8* bits, uint8 r, uint8 g, uint8 b) +{ + bits[0] = b; + bits[1] = g; + bits[2] = r; +// bits[3] = 255; +} + +// _UpdateThread +int32 +ColorField::_UpdateThread(void* data) +{ + // initializing + ColorField* colorField = (ColorField *)data; + + bool looperLocked = colorField->LockLooper(); + + BBitmap* bitmap = colorField->fBgBitmap[0]; + port_id port = colorField->fUpdatePort; + orientation orient = colorField->fOrientation; + + if (looperLocked) + colorField->UnlockLooper(); + + float h, s, v, r, g, b; + int R, G, B; + + // drawing + + int32 msg_code; + char msg_buffer; + + while (true) { + + port_info info; + + do { + + read_port(port, &msg_code, &msg_buffer, sizeof(msg_buffer)); + get_port_info(port, &info); + + } while (info.queue_count); + + if (colorField->LockLooper()) { + + uint colormode = colorField->fMode; + float fixedvalue = colorField->fFixedValue; + + int width = (int)colorField->Width(); + int height = (int)colorField->Height(); + + colorField->UnlockLooper(); + + bitmap->Lock(); + //bigtime_t now = system_time(); + uint8* bits = (uint8*)bitmap->Bits(); + uint32 bpr = bitmap->BytesPerRow(); + // offset 2 pixels from top and left + bits += 2 * 4 + 2 * bpr; + + switch (colormode) { + + case R_SELECTED: { + R = round(fixedvalue * 255); + for (int y = height; y >= 0; y--) { + uint8* bitsHandle = bits; + int B = y / height * 255; + for (int x = 0; x <= width; ++x) { + int G = x / width * 255; + set_bits(bitsHandle, R, G, B); + bitsHandle += 4; + } + bits += bpr; + } + }; break; + + case G_SELECTED: { + G = round(fixedvalue * 255); + for (int y = height; y >= 0; y--) { + uint8* bitsHandle = bits; + int B = y / height * 255; + for (int x = 0; x <= width; ++x) { + int R = x / width * 255; + set_bits(bitsHandle, R, G, B); + bitsHandle += 4; + } + bits += bpr; + } + }; break; + + case B_SELECTED: { + B = round(fixedvalue * 255); + for (int y = height; y >= 0; y--) { + uint8* bitsHandle = bits; + int G = y / height * 255; + for (int x = 0; x <= width; ++x) { + int R = x / width * 255; + set_bits(bitsHandle, R, G, B); + bitsHandle += 4; + } + bits += bpr; + } + }; break; + + case H_SELECTED: { + h = fixedvalue; + if (orient == B_VERTICAL) { + for (int y = 0; y <= height; ++y) { + v = (float)(height - y) / height; + uint8* bitsHandle = bits; + for (int x = 0; x <= width; ++x) { + s = (float)x / width; + HSV_to_RGB( h, s, v, r, g, b ); + set_bits(bitsHandle, round(r * 255.0), round(g * 255.0), round(b * 255.0)); + bitsHandle += 4; + } + bits += bpr; + } + } else { + for (int y = 0; y <= height; ++y) { + s = (float)y / height; + uint8* bitsHandle = bits; + for (int x = 0; x <= width; ++x) { + v = (float)(width - x) / width; + HSV_to_RGB( h, s, v, r, g, b ); + set_bits(bitsHandle, round(r * 255.0), round(g * 255.0), round(b * 255.0)); + bitsHandle += 4; + } + bits += bpr; + } + } + }; break; + + case S_SELECTED: { + s = fixedvalue; + for (int y = 0; y <= height; ++y) { + v = (float)(height - y) / height; + uint8* bitsHandle = bits; + for (int x = 0; x <= width; ++x) { + h = 6.0 / width * x; + HSV_to_RGB( h, s, v, r, g, b ); + set_bits(bitsHandle, round(r * 255.0), round(g * 255.0), round(b * 255.0)); + bitsHandle += 4; + } + bits += bpr; + } + }; break; + + case V_SELECTED: { + v = fixedvalue; + for (int y = 0; y <= height; ++y) { + s = (float)(height - y) / height; + uint8* bitsHandle = bits; + for (int x = 0; x <= width; ++x) { + h = 6.0 / width * x; + HSV_to_RGB( h, s, v, r, g, b ); + set_bits(bitsHandle, round(r * 255.0), round(g * 255.0), round(b * 255.0)); + bitsHandle += 4; + } + bits += bpr; + } + }; break; + } + + //printf("color field update: %lld\n", system_time() - now); + bitmap->Unlock(); + + if (colorField->LockLooper()) { + colorField->Update(2); + colorField->UnlockLooper(); + } + } + } +} + +// _DrawBorder +void +ColorField::_DrawBorder() +{ + bool looperLocked = LockLooper(); + + fBgBitmap[1]->Lock(); + + rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color shadow = tint_color(background, B_DARKEN_1_TINT); + rgb_color darkShadow = tint_color(background, B_DARKEN_3_TINT); + rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT); + + BRect r(fBgView[1]->Bounds()); + r.OffsetBy(-2.0, -2.0); + BRegion region(r); + fBgView[1]->ConstrainClippingRegion(®ion); + + r = Bounds(); + r.OffsetBy(-2.0, -2.0); + + stroke_frame(fBgView[1], r, shadow, shadow, light, light); + r.InsetBy(1.0, 1.0); + stroke_frame(fBgView[1], r, darkShadow, darkShadow, background, background); + r.InsetBy(1.0, 1.0); + + region.Set(r); + fBgView[1]->ConstrainClippingRegion(®ion); + + fBgBitmap[1]->Unlock(); + + if (looperLocked) + UnlockLooper(); +} diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorField.h b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorField.h new file mode 100644 index 0000000000..3fdb5f26df --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorField.h @@ -0,0 +1,93 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. + * + */ + +#ifndef _COLOR_FIELD_H +#define _COLOR_FIELD_H + +#include "ColorPickerDefs.h" + +#include + +#if LIB_LAYOUT +# include +#endif + +#include "selected_color_mode.h" + +enum { + MSG_COLOR_FIELD = 'ColF', +}; + +class BBitmap; + +class ColorField : + #if LIB_LAYOUT + public MView, + #endif + public BControl { + public: + ColorField(BPoint offset_point, + selected_color_mode mode, + float fixed_value, + orientation orient = B_VERTICAL); + virtual ~ColorField(); + + // MView + #if LIB_LAYOUT + virtual minimax layoutprefs(); + virtual BRect layout(BRect frame); + #endif + + // BControl + virtual status_t Invoke(BMessage *msg = NULL); + + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 code, + const BMessage* message); + + // ColorField + void Update(int depth); + + void SetModeAndValue(selected_color_mode mode, float fixed_value); + void SetFixedValue(float fixed_value); + float FixedValue() const + { return fFixedValue; } + + void SetMarkerToColor( rgb_color color ); + void PositionMarkerAt( BPoint where ); + + float Width() const; + float Height() const; + bool IsTracking() const + { return fMouseDown; } + + private: + static int32 _UpdateThread(void* data); + void _DrawBorder(); + + selected_color_mode fMode; + float fFixedValue; + orientation fOrientation; + + BPoint fMarkerPosition; + BPoint fLastMarkerPosition; + + bool fMouseDown; + + BBitmap* fBgBitmap[2]; + BView* fBgView[2]; + + thread_id fUpdateThread; + port_id fUpdatePort; +}; + +#endif diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerDefs.h b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerDefs.h new file mode 100644 index 0000000000..339c420dcd --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerDefs.h @@ -0,0 +1,6 @@ +#ifndef COLOR_PICKER_COMMON_H +#define COLOR_PICKER_COMMON_H + +#define LIB_LAYOUT 0 + +#endif // COLOR_PICKER_COMMON_H diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerPanel.cpp b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerPanel.cpp new file mode 100644 index 0000000000..49691e4fae --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerPanel.cpp @@ -0,0 +1,164 @@ +/* + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT license. + * + */ + +#include "ColorPickerPanel.h" + +#include + +#include + +#include "ColorPickerDefs.h" + +#if LIB_LAYOUT +# include +# include +# include +# include +# include +#else +# include +# include +#endif + +#include "support_ui.h" + +#include "ColorPickerView.h" + +enum { + MSG_CANCEL = 'cncl', + MSG_DONE = 'done', +}; + +// constructor +ColorPickerPanel::ColorPickerPanel(BRect frame, rgb_color color, + selected_color_mode mode, + BMessage* message, BWindow* target) + : Panel(frame, "Pick Color", + B_FLOATING_WINDOW_LOOK, B_FLOATING_SUBSET_WINDOW_FEEL, + B_ASYNCHRONOUS_CONTROLS | + B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_NOT_CLOSABLE), + fMessage(message), + fTarget(target) +{ + SetTitle("Pick Color"); + + fColorPickerView = new ColorPickerView("color picker", color, mode); + +#if LIB_LAYOUT + MButton* defaultButton = new MButton("Ok", new BMessage(MSG_DONE), this); + + // interface layout + BView* topView = new VGroup ( + fColorPickerView, + new MBorder ( + M_RAISED_BORDER, 5, "buttons", + new HGroup ( + new Space(minimax(0.0, 0.0, 10000.0, 10000.0, 5.0)), + new MButton("Cancel", new BMessage(MSG_CANCEL), this), + new Space(minimax(5.0, 0.0, 10.0, 10000.0, 1.0)), + defaultButton, + new Space(minimax(2.0, 0.0, 2.0, 10000.0, 0.0)), + 0 + ) + ), + 0 + ); +#else // LIB_LAYOUT + frame = BRect(0, 0, 40, 15); + BButton* defaultButton = new BButton(frame, "ok button", "Ok", + new BMessage(MSG_DONE), + B_FOLLOW_RIGHT | B_FOLLOW_TOP); + defaultButton->ResizeToPreferred(); + BButton* cancelButton = new BButton(frame, "cancel button", "Cancel", + new BMessage(MSG_CANCEL), + B_FOLLOW_RIGHT | B_FOLLOW_TOP); + cancelButton->ResizeToPreferred(); + + frame.bottom = frame.top + (defaultButton->Frame().Height() + 16); + frame.right = frame.left + fColorPickerView->Frame().Width(); + BBox* buttonBox = new BBox(frame, "button group", + B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, + B_PLAIN_BORDER); + + ResizeTo(frame.Width(), + fColorPickerView->Frame().Height() + frame.Height() + 1); + + frame = Bounds(); + BView* topView = new BView(frame, "bg", B_FOLLOW_ALL, 0); + topView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + buttonBox->MoveTo(frame.left, frame.bottom - buttonBox->Frame().Height()); + + defaultButton->MoveTo(frame.right - defaultButton->Frame().Width() - 10, + frame.top + 8); + buttonBox->AddChild(defaultButton); + + cancelButton->MoveTo(defaultButton->Frame().left - 10 + - cancelButton->Frame().Width(), + frame.top + 8); + buttonBox->AddChild(cancelButton); + + topView->AddChild(fColorPickerView); + topView->AddChild(buttonBox); +#endif // LIB_LAYOUT + + SetDefaultButton(defaultButton); + + if (fTarget) + AddToSubset(fTarget); + else + SetFeel(B_FLOATING_APP_WINDOW_FEEL); + + AddChild(topView); +} + +// destructor +ColorPickerPanel::~ColorPickerPanel() +{ + delete fMessage; +} + +// Cancel +void +ColorPickerPanel::Cancel() +{ + PostMessage(MSG_CANCEL); +} + +// MessageReceived +void +ColorPickerPanel::MessageReceived(BMessage* message) +{ + switch (message->what) { + case MSG_CANCEL: + case MSG_DONE: { + BMessage msg('PSTE'); + BLooper* looper = fTarget ? static_cast(fTarget) + : static_cast(be_app); + if (fMessage) + msg = *fMessage; + if (message->what == MSG_DONE) + store_color_in_message(&msg, fColorPickerView->Color()); + msg.AddRect("panel frame", Frame()); + msg.AddInt32("panel mode", fColorPickerView->Mode()); + msg.AddBool("begin", true); + looper->PostMessage(&msg); + PostMessage(B_QUIT_REQUESTED); + break; + } + default: + Panel::MessageReceived(message); + break; + } +} + +// SetColor +void +ColorPickerPanel::SetColor(rgb_color color) +{ + fColorPickerView->SetColor(color); +} diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerPanel.h b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerPanel.h new file mode 100644 index 0000000000..f1a095be0b --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerPanel.h @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. Distributed under the terms of the MIT license. + * + */ + +#ifndef COLOR_PICKER_PANEL_H +#define COLOR_PICKER_PANEL_H + +#include "Panel.h" + +#include "selected_color_mode.h" + +class ColorPickerView; + +class ColorPickerPanel : public Panel { + public: + ColorPickerPanel(BRect frame, + rgb_color color, + selected_color_mode mode + = H_SELECTED, + BMessage* message = NULL, + BWindow* target = NULL); + virtual ~ColorPickerPanel(); + + // Panel + virtual void Cancel(); + + virtual void MessageReceived(BMessage* message); + + void SetColor(rgb_color color); + + private: + + ColorPickerView* fColorPickerView; + BMessage* fMessage; + BWindow* fTarget; +}; + +#endif // COLOR_PICKER_PANEL_H diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerView.cpp b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerView.cpp new file mode 100644 index 0000000000..4633d2e36c --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerView.cpp @@ -0,0 +1,504 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ColorField.h" +#include "ColorPreview.h" +#include "ColorSlider.h" +#include "rgb_hsv.h" + +#include "ColorPickerView.h" + + +#define round(x) (int)(x+.5) +#define hexdec(str, offset) (int)(((str[offset]<60?str[offset]-48:(str[offset]|32)-87)<<4)|(str[offset+1]<60?str[offset+1]-48:(str[offset+1]|32)-87)) + +// constructor +ColorPickerView::ColorPickerView(const char* name, rgb_color color, + selected_color_mode mode) + : BView(BRect(0.0, 0.0, 400.0, 277.0), name, + B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED), + h(0.0), + s(1.0), + v(1.0), + r((float)color.red / 255.0), + g((float)color.green / 255.0), + b((float)color.blue / 255.0), + fRequiresUpdate(false) + +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + + RGB_to_HSV(r, g, b, h, s, v); + + SetColorMode(mode, false); +} + +// destructor +ColorPickerView::~ColorPickerView() +{ +} + +#if LIB_LAYOUT +// layoutprefs +minimax +ColorPickerView::layoutprefs() +{ + mpm.mini.x = mpm.maxi.x = Bounds().Width() + 1.0; + mpm.mini.y = mpm.maxi.y = Bounds().Height() + 1.0; + mpm.weight = 1.0; + return mpm; +} + +// layout +BRect +ColorPickerView::layout(BRect frame) +{ + MoveTo(frame.LeftTop()); + ResizeTo(frame.Width(), frame.Height()); + return Frame(); +} +#endif // LIB_LAYOUT + +// AttachedToWindow +void +ColorPickerView::AttachedToWindow() +{ + rgb_color color = { (int)(r * 255), (int)(g * 255), (int)(b * 255), 255 }; + + BView::AttachedToWindow(); + + fColorField = new ColorField(BPoint(10.0, 10.0), fSelectedColorMode, *p); + fColorField->SetMarkerToColor(color); + AddChild(fColorField); + fColorField->SetTarget(this); + + fColorSlider = new ColorSlider(BPoint(278.0, 7.0), fSelectedColorMode, *p1, *p2); + fColorSlider->SetMarkerToColor(color); + AddChild(fColorSlider); + fColorSlider->SetTarget(this); + + fColorPreview = new ColorPreview(BRect(0.0, 0.0, 66.0, 70.0).OffsetToCopy(321.0, 10.0), color); + AddChild(fColorPreview); + fColorPreview->SetTarget(this); + + BFont font(be_plain_font); + font.SetSize(10.0); + SetFont(&font); + + const char *title[] = { "H", "S", "V", "R", "G", "B" }; + + BTextView *textView; + + int32 selectedRadioButton = _NumForMode(fSelectedColorMode); + for (int i=0; i<6; ++i) { + + fRadioButton[i] = new BRadioButton(BRect(0.0, 0.0, 30.0, 10.0).OffsetToCopy(320.0, 92.0 + 24.0 * i + (int)i/3 * 8), + NULL, title[i], new BMessage(MSG_RADIOBUTTON + i)); + fRadioButton[i]->SetFont(&font); + AddChild(fRadioButton[i]); + + fRadioButton[i]->SetTarget(this); + + if (i == selectedRadioButton) + fRadioButton[i]->SetValue(1); + } + + for (int i=0; i<6; ++i) { + + fTextControl[i] = new BTextControl(BRect(0.0, 0.0, 32.0, 19.0).OffsetToCopy(350.0, 90.0 + 24.0 * i + (int)i/3 * 8), + NULL, NULL, NULL, new BMessage(MSG_TEXTCONTROL + i)); + + textView = fTextControl[i]->TextView(); + textView->SetMaxBytes(3); + for (int j=32; j<255; ++j) { + if (j<'0'||j>'9') textView->DisallowChar(j); + } + + fTextControl[i]->SetFont(&font); + fTextControl[i]->SetDivider(0.0); + AddChild(fTextControl[i]); + + fTextControl[i]->SetTarget(this); + } + + fHexTextControl = new BTextControl(BRect(0.0, 0.0, 69.0, 19.0).OffsetToCopy(320.0, 248.0), + NULL, "#", NULL, new BMessage(MSG_HEXTEXTCONTROL)); + + textView = fHexTextControl->TextView(); + textView->SetMaxBytes(6); + for (int j=32; j<255; ++j) { + if (!((j>='0' && j<='9') || (j>='a' && j<='f') || (j>='A' && j<='F'))) textView->DisallowChar(j); + } + + fHexTextControl->SetFont(&font); + fHexTextControl->SetDivider(12.0); + AddChild(fHexTextControl); + + fHexTextControl->SetTarget(this); + + _UpdateTextControls(); +} + +// MessageReceived +void +ColorPickerView::MessageReceived(BMessage *message) +{ + switch (message->what) { + + case MSG_COLOR_FIELD: { + float value1, value2; + value1 = message->FindFloat("value"); + value2 = message->FindFloat("value", 1); + _UpdateColor(-1, value1, value2); + fRequiresUpdate = true; + } break; + + case MSG_COLOR_SLIDER: { + float value; + message->FindFloat("value", &value); + _UpdateColor(value, -1, -1); + fRequiresUpdate = true; + } break; + + case MSG_COLOR_PREVIEW: { + rgb_color *color; + ssize_t numBytes; + if (message->FindData("color", B_RGB_COLOR_TYPE, (const void **)&color, &numBytes)==B_OK) { + color->alpha = 255; + SetColor(*color); + } + } break; + + case MSG_RADIOBUTTON: { + SetColorMode(H_SELECTED); + } break; + + case MSG_RADIOBUTTON + 1: { + SetColorMode(S_SELECTED); + } break; + + case MSG_RADIOBUTTON + 2: { + SetColorMode(V_SELECTED); + } break; + + case MSG_RADIOBUTTON + 3: { + SetColorMode(R_SELECTED); + } break; + + case MSG_RADIOBUTTON + 4: { + SetColorMode(G_SELECTED); + } break; + + case MSG_RADIOBUTTON + 5: { + SetColorMode(B_SELECTED); + } break; + + case MSG_TEXTCONTROL: + case MSG_TEXTCONTROL + 1: + case MSG_TEXTCONTROL + 2: + case MSG_TEXTCONTROL + 3: + case MSG_TEXTCONTROL + 4: + case MSG_TEXTCONTROL + 5: { + + int nr = message->what - MSG_TEXTCONTROL; + int value = atoi(fTextControl[nr]->Text()); + + char string[4]; + + switch (nr) { + case 0: { + value %= 360; + sprintf(string, "%d", value); + h = (float)value / 60; + } break; + + case 1: { + value = min_c(value, 100); + sprintf(string, "%d", value); + s = (float)value / 100; + } break; + + case 2: { + value = min_c(value, 100); + sprintf(string, "%d", value); + v = (float)value / 100; + } break; + + case 3: { + value = min_c(value, 255); + sprintf(string, "%d", value); + r = (float)value / 255; + } break; + + case 4: { + value = min_c(value, 255); + sprintf(string, "%d", value); + g = (float)value / 255; + } break; + + case 5: { + value = min_c(value, 255); + sprintf(string, "%d", value); + b = (float)value / 255; + } break; + } + + if (nr<3) { // hsv-mode + HSV_to_RGB(h, s, v, r, g, b); + } + + rgb_color color = { round(r*255), round(g*255), round(b*255), 255 }; + + SetColor(color); + + } break; + + case MSG_HEXTEXTCONTROL: { + if (fHexTextControl->TextView()->TextLength()==6) { + const char *string = fHexTextControl->TextView()->Text(); + rgb_color color = { hexdec(string, 0), hexdec(string, 2), hexdec(string, 4), 255 }; + SetColor(color); + } + } break; + + default: + BView::MessageReceived(message); + } +} + +// Draw +void +ColorPickerView::Draw(BRect updateRect) +{ + // raised border + BRect r(Bounds()); + if (updateRect.Intersects(r)) { + rgb_color light = tint_color(LowColor(), B_LIGHTEN_MAX_TINT); + rgb_color shadow = tint_color(LowColor(), B_DARKEN_2_TINT); + + BeginLineArray(4); + AddLine(BPoint(r.left, r.bottom), + BPoint(r.left, r.top), light); + AddLine(BPoint(r.left + 1.0, r.top), + BPoint(r.right, r.top), light); + AddLine(BPoint(r.right, r.top + 1.0), + BPoint(r.right, r.bottom), shadow); + AddLine(BPoint(r.right - 1.0, r.bottom), + BPoint(r.left + 1.0, r.bottom), shadow); + EndLineArray(); + // exclude border from update rect + r.InsetBy(1.0, 1.0); + updateRect = r & updateRect; + } + + // some additional labels + font_height fh; + GetFontHeight(&fh); + + const char *title[] = { "°", "%", "%" }; + for (int i = 0; i < 3; ++i) { + DrawString(title[i], + BPoint(385.0, 93.0 + 24.0 * i + (int)i / 3 * 8 + fh.ascent)); + } +} + +// Pulse +void +ColorPickerView::Pulse() +{ + if (fRequiresUpdate) + _UpdateTextControls(); +} + +// SetColorMode +void +ColorPickerView::SetColorMode(selected_color_mode mode, bool update) +{ + fSelectedColorMode = mode; + switch (mode) { + case R_SELECTED: + p = &r; p1 = &g; p2 = &b; + break; + + case G_SELECTED: + p = &g; p1 = &r; p2 = &b; + break; + + case B_SELECTED: + p = &b; p1 = &r; p2 = &g; + break; + + case H_SELECTED: + p = &h; p1 = &s; p2 = &v; + break; + + case S_SELECTED: + p = &s; p1 = &h; p2 = &v; + break; + + case V_SELECTED: + p = &v; p1 = &h; p2 = &s; + break; + } + + if (!update) return; + + fColorSlider->SetModeAndValues(fSelectedColorMode, *p1, *p2); + fColorField->SetModeAndValue(fSelectedColorMode, *p); + +} + +// SetColor +void +ColorPickerView::SetColor(rgb_color color) +{ + r = (float)color.red/255; g = (float)color.green/255; b = (float)color.blue/255; + RGB_to_HSV(r, g, b, h, s, v); + + fColorSlider->SetModeAndValues(fSelectedColorMode, *p1, *p2); + fColorSlider->SetMarkerToColor(color); + + fColorField->SetModeAndValue(fSelectedColorMode, *p); + fColorField->SetMarkerToColor(color); + + fColorPreview->SetColor(color); + + fRequiresUpdate = true; +} + +// Color +rgb_color +ColorPickerView::Color() +{ + if (fSelectedColorMode & (R_SELECTED|G_SELECTED|B_SELECTED)) + RGB_to_HSV(r, g, b, h, s, v); + else + HSV_to_RGB(h, s, v, r, g, b); + + rgb_color color; + color.red = (uint8)round(r * 255.0); + color.green = (uint8)round(g * 255.0); + color.blue = (uint8)round(b * 255.0); + color.alpha = 255; + + return color; +} + +// _NumForMode +int32 +ColorPickerView::_NumForMode(selected_color_mode mode) const +{ + int32 num = -1; + switch (mode) { + case H_SELECTED: + num = 0; + break; + case S_SELECTED: + num = 1; + break; + case V_SELECTED: + num = 2; + break; + case R_SELECTED: + num = 3; + break; + case G_SELECTED: + num = 4; + break; + case B_SELECTED: + num = 5; + break; + } + return num; +} + +// _UpdateColor +void +ColorPickerView::_UpdateColor(float value, float value1, float value2) +{ + if (value!=-1) { + fColorField->SetFixedValue(value); + *p = value; + } + else if (value1!=-1 && value2!=-1) { + fColorSlider->SetOtherValues(value1, value2); + *p1 = value1; *p2 = value2; + } + + if (fSelectedColorMode & (R_SELECTED|G_SELECTED|B_SELECTED)) + RGB_to_HSV(r, g, b, h, s, v); + else + HSV_to_RGB(h, s, v, r, g, b); + + rgb_color color = { (int)(r*255), (int)(g*255), (int)(b*255), 255 }; + fColorPreview->SetColor(color); +} + +// _UpdateTextControls +void +ColorPickerView::_UpdateTextControls() +{ + Window()->DisableUpdates(); + + char string[10]; + + fRequiresUpdate = false; + + sprintf(string, "%d", round(h*60)); + _SetText(fTextControl[0], string, &fRequiresUpdate); + + sprintf(string, "%d", round(s*100)); + _SetText(fTextControl[1], string, &fRequiresUpdate); + + sprintf(string, "%d", round(v*100)); + _SetText(fTextControl[2], string, &fRequiresUpdate); + + sprintf(string, "%d", round(r*255)); + _SetText(fTextControl[3], string, &fRequiresUpdate); + + sprintf(string, "%d", round(g*255)); + _SetText(fTextControl[4], string, &fRequiresUpdate); + + sprintf(string, "%d", round(b*255)); + _SetText(fTextControl[5], string, &fRequiresUpdate); + + sprintf(string, "%.6X", (round(r*255)<<16)|(round(g*255)<<8)|round(b*255)); + _SetText(fHexTextControl, string, &fRequiresUpdate); + + Window()->EnableUpdates(); +} + +// _SetText +void +ColorPickerView::_SetText(BTextControl* control, const char* text, + bool* requiresUpdate) +{ + if (strcmp(control->Text(), text) != 0) { + // this textview needs updating + if (!control->TextView()->IsFocus()) + // but don't screw with user while she is typing + control->SetText(text); + else + *requiresUpdate = true; + } +} + diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerView.h b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerView.h new file mode 100644 index 0000000000..c79ce0ad42 --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPickerView.h @@ -0,0 +1,94 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. + * + */ + +#ifndef COLOR_PICKER_VIEW_H +#define COLOR_PICKER_VIEW_H + +#include "ColorPickerDefs.h" + +#include + +#if LIB_LAYOUT +# include +#endif + +#include "selected_color_mode.h" + +#define MSG_RADIOBUTTON 'Rad0' +#define MSG_TEXTCONTROL 'Txt0' +#define MSG_HEXTEXTCONTROL 'HTxt' + +class ColorField; +class ColorSlider; +class ColorPreview; + +class BRadioButton; +class BTextControl; + +class ColorPickerView : + #if LIB_LAYOUT + public MView, + #endif + public BView { + public: + ColorPickerView(const char* name, + rgb_color color, + selected_color_mode mode); + virtual ~ColorPickerView(); + + #if LIB_LAYOUT + // MView + virtual minimax layoutprefs(); + virtual BRect layout(BRect frame); + #endif + + // BView + virtual void AttachedToWindow(); + virtual void MessageReceived(BMessage *message); + + virtual void Draw(BRect updateRect); + virtual void Pulse(); + + // ColorPickerView + void SetColorMode(selected_color_mode mode, + bool update = true); + void SetColor(rgb_color color); + rgb_color Color(); + selected_color_mode Mode() const + { return fSelectedColorMode; } + + private: + int32 _NumForMode(selected_color_mode mode) const; + + void _UpdateColor(float value, float value1, + float value2); + void _UpdateTextControls(); + void _SetText(BTextControl* control, + const char* text, + bool* requiresUpdate); + + + selected_color_mode fSelectedColorMode; + + float h, s, v, r, g, b; + float *p, *p1, *p2; + + bool fRequiresUpdate; + + ColorField* fColorField; + ColorSlider* fColorSlider; + ColorPreview* fColorPreview; + + BRadioButton* fRadioButton[6]; + BTextControl* fTextControl[6]; + BTextControl* fHexTextControl; +}; + +#endif // COLOR_PICKER_VIEW_H + + diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPreview.cpp b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPreview.cpp new file mode 100644 index 0000000000..b729b805c0 --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPreview.cpp @@ -0,0 +1,211 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. + * + */ + +#include "ColorPreview.h" + +#include + +#include +#include +#include +#include +#include + +#include "cursors.h" +#include "support_ui.h" + +// constructor +ColorPreview::ColorPreview(BRect frame, rgb_color color) + : BControl(frame, "colorpreview", "", new BMessage(MSG_COLOR_PREVIEW), + B_FOLLOW_TOP|B_FOLLOW_LEFT, B_WILL_DRAW), + fColor(color), + fOldColor(color), + + fMouseDown(false), + + fMessageRunner(0) +{ +} + +// AttachedToWindow +void +ColorPreview::AttachedToWindow() +{ + BControl::AttachedToWindow(); + SetViewColor(B_TRANSPARENT_COLOR); +} + +// Draw +void +ColorPreview::Draw(BRect updateRect) +{ + rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color shadow = tint_color(background, B_DARKEN_1_TINT); + rgb_color darkShadow = tint_color(background, B_DARKEN_3_TINT); + rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT); + + BRect r(Bounds()); + stroke_frame(this, r, shadow, shadow, light, light); + r.InsetBy(1.0, 1.0); + stroke_frame(this, r, darkShadow, darkShadow, background, background); + r.InsetBy(1.0, 1.0); + + r.bottom = r.top + r.Height() / 2.0; + SetHighColor(fColor); + FillRect(r); + + r.top = r.bottom + 1; + r.bottom = Bounds().bottom - 2.0; + SetHighColor(fOldColor); + FillRect(r); +} + +// MessageReceived +void +ColorPreview::MessageReceived(BMessage* message) +{ + if (message->what == MSG_MESSAGERUNNER) { + + BPoint where; + uint32 buttons; + + GetMouse(&where, &buttons); + + _DragColor(where); + + } else { +#ifdef TARGET_PLATFORM_ZETA + const +#endif + char* nameFound; + type_code typeFound; + + if (message->GetInfo(B_RGB_COLOR_TYPE, 0, + &nameFound, &typeFound) != B_OK) { + BControl::MessageReceived(message); + return; + } + + rgb_color* color; + ssize_t numBytes; + message->FindData(nameFound, typeFound, + (const void**)&color, &numBytes); + + BPoint where; + bool droppedOnNewArea = false; + if (message->FindPoint("_drop_point_", &where) == B_OK) { + ConvertFromScreen(&where); + if (where.y > Bounds().top + (Bounds().IntegerHeight() >> 1)) + droppedOnNewArea = true; + } + + if (droppedOnNewArea) + SetNewColor(*color); + else + SetColor(*color); + Invoke(); + } +} + +// MouseDown +void +ColorPreview::MouseDown(BPoint where) +{ + Window()->Activate(); + + fMouseDown = true; + + fMessageRunner = new BMessageRunner( + this, new BMessage(MSG_MESSAGERUNNER), 300000, 1); + + SetMouseEventMask(B_POINTER_EVENTS, + B_SUSPEND_VIEW_FOCUS | B_LOCK_WINDOW_FOCUS); + + BRect rect = Bounds().InsetByCopy(2.0, 2.0); + rect.top = rect.bottom/2 + 1; + + if (rect.Contains( where ) ) { + fColor = fOldColor; + Draw( Bounds() ); + Invoke(); + } + +} + +// MouseUp +void +ColorPreview::MouseUp(BPoint where) +{ + delete fMessageRunner; + fMessageRunner = NULL; + + fMouseDown = false; + BControl::MouseUp(where); +} + +// MouseMoved +void +ColorPreview::MouseMoved(BPoint where, uint32 transit, const BMessage* message) +{ + if (transit == B_ENTERED_VIEW) { + BCursor cursor(kDropperCursor); + SetViewCursor(&cursor, true); + } + if (fMouseDown) + _DragColor(where); +} + +// Invoke +status_t +ColorPreview::Invoke(BMessage* message) +{ + if (!message) + message = Message(); + + if (message) { + message->RemoveName("color"); + message->AddData("color", B_RGB_COLOR_TYPE, &fColor, sizeof(fColor)); + } + + return BControl::Invoke(message); +} + +// SetColor +void +ColorPreview::SetColor(rgb_color color) +{ + color.alpha = 255; + fColor = color; + + Invalidate(); +} + +// SetNewColor +void +ColorPreview::SetNewColor(rgb_color color) +{ + fColor = color; + fOldColor = color; + + Invalidate(); +} + +// #pragma mark - + +// _DragColor +void +ColorPreview::_DragColor(BPoint where) +{ + BBitmap* bitmap = new BBitmap(BRect(0.0, 0.0, 15.0, 15.0), B_RGB32); + BMessage message = make_color_drop_message(fColor, bitmap); + + DragMessage(&message, bitmap, B_OP_ALPHA, BPoint(9.0, 9.0)); + + MouseUp(where); +} + diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPreview.h b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPreview.h new file mode 100644 index 0000000000..8f137b968f --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorPreview.h @@ -0,0 +1,57 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. + * + */ + +#ifndef _COLOR_PREVIEW_H +#define _COLOR_PREVIEW_H + +#include + +#define MSG_COLOR_PREVIEW 'ColP' +#define MSG_MESSAGERUNNER 'MsgR' + +class BMessageRunner; + +class ColorPreview : public BControl { + public: + + ColorPreview(BRect frame, + rgb_color color); + + // BControl interface + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); + + virtual void MessageReceived(BMessage* message); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* message); + + virtual status_t Invoke(BMessage* message = NULL); + + // ColorPreview + void SetColor(rgb_color color); + // changes the displayed color + void SetNewColor(rgb_color color); + // changes also the old color + + private: + + void _DragColor(BPoint where); + + rgb_color fColor; + rgb_color fOldColor; + + bool fMouseDown; + + BMessageRunner* fMessageRunner; +}; + +#endif // _COLOR_PREVIEW_H + diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorSlider.cpp b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorSlider.cpp new file mode 100644 index 0000000000..3d40199f8d --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorSlider.cpp @@ -0,0 +1,669 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. + * + */ + +#include "ColorSlider.h" + +#include + +#include +#include +#include +#include + +#include "selected_color_mode.h" +#include "support_ui.h" + +#include "rgb_hsv.h" + +#define round(x) (int)(x+.5) + +enum { + MSG_UPDATE = 'Updt', +}; + +#define MAX_X 255 +#define MAX_Y 255 + +// constructor +ColorSlider::ColorSlider(BPoint offset_point, + selected_color_mode mode, + float value1, float value2, orientation dir) + : BControl(BRect(0.0, 0.0, 35.0, 265.0).OffsetToCopy(offset_point), + "ColorSlider", "", new BMessage(MSG_COLOR_SLIDER), + B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_FRAME_EVENTS), + fMode(mode), + fFixedValue1(value1), + fFixedValue2(value2), + fMouseDown(false), + fBgBitmap(new BBitmap(Bounds(), B_RGB32, true)), + fBgView(NULL), + fUpdateThread(0), + fUpdatePort(0), + fOrientation(dir) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + + if (fBgBitmap->IsValid() && fBgBitmap->Lock()) { + fBgView = new BView(Bounds(), "", B_FOLLOW_NONE, B_WILL_DRAW); + fBgBitmap->AddChild(fBgView); +/* if (fOrientation == B_VERTICAL) + fBgView->SetOrigin(8.0, 2.0); + else + fBgView->SetOrigin(2.0, 2.0);*/ + fBgBitmap->Unlock(); + } else { + delete fBgBitmap; + fBgBitmap = NULL; + fBgView = this; + } + + fUpdatePort = create_port(100, "color slider update port"); + + fUpdateThread = spawn_thread(ColorSlider::_UpdateThread, "color slider update thread", 10, this); + resume_thread( fUpdateThread ); + + Update(2); +} + +// destructor +ColorSlider::~ColorSlider() +{ + if (fUpdatePort) + delete_port(fUpdatePort); + if (fUpdateThread) + kill_thread(fUpdateThread); + + delete fBgBitmap; +} + +#if LIB_LAYOUT +// layoutprefs +minimax +ColorSlider::layoutprefs() +{ + if (fOrientation == B_VERTICAL) { + mpm.mini.x = 36; + mpm.maxi.x = 36; + mpm.mini.y = 10 + MAX_Y / 17; + mpm.maxi.y = 10 + MAX_Y; + } else { + mpm.mini.x = 10 + MAX_X / 17; + mpm.maxi.x = 10 + MAX_X; + mpm.mini.y = 10.0; + mpm.maxi.y = 12.0; + } + mpm.weight = 1.0; + + return mpm; +} + +// layout +BRect +ColorSlider::layout(BRect frame) +{ + MoveTo(frame.LeftTop()); + ResizeTo(frame.Width(), frame.Height()); +// Update(2); + return Frame(); +} +#endif // LIB_LAYOUT + +// AttachedToWindow +void +ColorSlider::AttachedToWindow() +{ + BControl::AttachedToWindow(); + + SetViewColor(B_TRANSPARENT_32_BIT); + + if (fBgBitmap && fBgBitmap->Lock()) { + fBgView->SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + fBgView->FillRect(Bounds()); + fBgBitmap->Unlock(); + } else { + SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + } + + Update(2); +} + + +// Invoke +status_t +ColorSlider::Invoke(BMessage *msg) +{ + if (!msg) msg = Message(); + + msg->RemoveName("value"); + msg->RemoveName("begin"); + + switch (fMode) { + + case R_SELECTED: + case G_SELECTED: + case B_SELECTED: { + msg->AddFloat("value", 1.0 - (float)Value() / 255); + } break; + + case H_SELECTED: { + msg->AddFloat("value", (1.0 - (float)Value() / 255) * 6); + } break; + + case S_SELECTED: + case V_SELECTED: { + msg->AddFloat("value", 1.0 - (float)Value() / 255); + } break; + + } + + // some other parts of WonderBrush rely on this. + // if the flag is present, it triggers generating an undo action + // fMouseDown is not set yet the first message is sent + if (!fMouseDown) + msg->AddBool("begin", true); + + return BControl::Invoke(msg); +} + +// Draw +void +ColorSlider::Draw(BRect updateRect) +{ + Update(0); +} + +// FrameResized +void +ColorSlider::FrameResized(float width, float height) +{ + if (fBgBitmap) { + fBgBitmap->Lock(); + delete fBgBitmap; + } + fBgBitmap = new BBitmap(Bounds(), B_RGB32, true); + if (fBgBitmap->IsValid() && fBgBitmap->Lock()) { + fBgView = new BView(Bounds(), "", B_FOLLOW_NONE, B_WILL_DRAW); + fBgBitmap->AddChild(fBgView); +/* if (fOrientation == B_VERTICAL) + fBgView->SetOrigin(8.0, 2.0); + else + fBgView->SetOrigin(2.0, 2.0);*/ + fBgBitmap->Unlock(); + } else { + delete fBgBitmap; + fBgBitmap = NULL; + fBgView = this; + } + Update(2); +} + +// MouseDown +void +ColorSlider::MouseDown(BPoint where) +{ + Window()->Activate(); + + SetMouseEventMask(B_POINTER_EVENTS, B_SUSPEND_VIEW_FOCUS | B_LOCK_WINDOW_FOCUS); + _TrackMouse(where); + fMouseDown = true; +} + +// MouseUp +void +ColorSlider::MouseUp(BPoint where) +{ + fMouseDown = false; +} + +// MouseMoved +void +ColorSlider::MouseMoved( BPoint where, uint32 code, const BMessage* dragMessage) +{ + if (dragMessage || !fMouseDown) + return; + + _TrackMouse(where); +} + +// SetValue +void +ColorSlider::SetValue(int32 value) +{ + value = max_c(min_c(value, 255), 0); + if (value != Value()) { + BControl::SetValue(value); + + Update(1); + } +} + +// Update +void +ColorSlider::Update(int depth) +{ + // depth: 0 = onscreen only, 1 = bitmap 1, 2 = bitmap 0 + if (depth == 2) { + write_port(fUpdatePort, MSG_UPDATE, NULL, 0); + return; + } + + if (!Parent()) + return; + + fBgBitmap->Lock(); + +// BRect r(fBgView->Bounds()); + BRect r(Bounds()); + BRect bounds(r); + if (fOrientation == B_VERTICAL) { +// r.OffsetBy(-8.0, -2.0); + r.InsetBy(6.0, 3.0); +// bounds.Set(-8.0, -2.0, r.right - 8.0, r.bottom - 2.0); +// bounds.OffsetBy(8.0, 2.0); + } else { +// r.OffsetBy(-2.0, -2.0); +// bounds.Set(-2.0, -2.0, r.right - 2.0, r.bottom - 2.0); +// bounds.OffsetBy(2.0, 2.0); + } + + fBgBitmap->Unlock(); + + rgb_color background = ui_color(B_PANEL_BACKGROUND_COLOR); + rgb_color shadow = tint_color(background, B_DARKEN_1_TINT); + rgb_color darkShadow = tint_color(background, B_DARKEN_3_TINT); + rgb_color light = tint_color(background, B_LIGHTEN_MAX_TINT); + + if (depth >= 1) { + + fBgBitmap->Lock(); + + + // frame + stroke_frame(fBgView, r, shadow, shadow, light, light); + r.InsetBy(1.0, 1.0); + stroke_frame(fBgView, r, darkShadow, darkShadow, background, background); + + if (fOrientation == B_VERTICAL) { + // clear area left and right from slider + fBgView->SetHighColor( background ); + fBgView->FillRect( BRect(bounds.left, bounds.top, bounds.left + 5.0, bounds.bottom) ); + fBgView->FillRect( BRect(bounds.right - 5.0, bounds.top, bounds.right, bounds.bottom) ); + } +/* + // marker + if (fOrientation == B_VERTICAL) { + // clear area left and right from slider + fBgView->SetHighColor( background ); + fBgView->FillRect( BRect(bounds.left, bounds.top, bounds.left + 5.0, bounds.bottom) ); + fBgView->FillRect( BRect(bounds.right - 5.0, bounds.top, bounds.right, bounds.bottom) ); + // draw the triangle markers + fBgView->SetHighColor( 0, 0, 0 ); + float value = Value(); + fBgView->StrokeLine( BPoint(bounds.left, value - 2.0), BPoint(bounds.left + 5.0, value + 3.0)); + fBgView->StrokeLine( BPoint(bounds.left, value + 8.0)); + fBgView->StrokeLine( BPoint(bounds.left, value - 2.0)); + + fBgView->StrokeLine( BPoint(bounds.right, value - 2.0), BPoint(bounds.right - 5.0, value + 3.0)); + fBgView->StrokeLine( BPoint(bounds.right, value + 8.0)); + fBgView->StrokeLine( BPoint(bounds.right, value - 2.0)); + } else { + r.InsetBy(1.0, 1.0); + float value = (Value() / 255.0) * (bounds.Width() - 4.0); + if (value - 2 > r.left) { + fBgView->SetHighColor( 255, 255, 255 ); + fBgView->StrokeLine( BPoint(value - 2, bounds.top + 2.0), + BPoint(value - 2, bounds.bottom - 2.0)); + } + if (value - 1 > r.left) { + fBgView->SetHighColor( 0, 0, 0 ); + fBgView->StrokeLine( BPoint(value - 1, bounds.top + 2.0), + BPoint(value - 1, bounds.bottom - 2.0)); + } + if (value + 1 < r.right) { + fBgView->SetHighColor( 0, 0, 0 ); + fBgView->StrokeLine( BPoint(value + 1, bounds.top + 2.0), + BPoint(value + 1, bounds.bottom - 2.0)); + } + if (value + 2 < r.right) { + fBgView->SetHighColor( 255, 255, 255 ); + fBgView->StrokeLine( BPoint(value + 2, bounds.top + 2.0), + BPoint(value + 2, bounds.bottom - 2.0)); + } + }*/ + + fBgView->Sync(); + + fBgBitmap->Unlock(); + } else + r.InsetBy(1.0, 1.0); + + DrawBitmap(fBgBitmap, BPoint(0.0, 0.0)); + + // marker + if (fOrientation == B_VERTICAL) { + // draw the triangle markers + SetHighColor( 0, 0, 0 ); + float value = Value(); + StrokeLine( BPoint(bounds.left, value), + BPoint(bounds.left + 5.0, value + 5.0)); + StrokeLine( BPoint(bounds.left, value + 10.0)); + StrokeLine( BPoint(bounds.left, value)); + + StrokeLine( BPoint(bounds.right, value), + BPoint(bounds.right - 5.0, value + 5.0)); + StrokeLine( BPoint(bounds.right, value + 10.0)); + StrokeLine( BPoint(bounds.right, value)); + } else { + r.InsetBy(1.0, 1.0); + float value = (Value() / 255.0) * (bounds.Width() - 4.0); + if (value > r.left) { + SetHighColor( 255, 255, 255 ); + StrokeLine( BPoint(value, bounds.top + 2.0), + BPoint(value, bounds.bottom - 2.0)); + } + if (value + 1 > r.left) { + SetHighColor( 0, 0, 0 ); + StrokeLine( BPoint(value + 1, bounds.top + 2.0), + BPoint(value + 1, bounds.bottom - 2.0)); + } + if (value + 3 < r.right) { + SetHighColor( 0, 0, 0 ); + StrokeLine( BPoint(value + 3, bounds.top + 2.0), + BPoint(value + 3, bounds.bottom - 2.0)); + } + if (value + 4 < r.right) { + SetHighColor( 255, 255, 255 ); + StrokeLine( BPoint(value + 4, bounds.top + 2.0), + BPoint(value + 4, bounds.bottom - 2.0)); + } + } + SetOrigin(0.0, 0.0); +} + +// SetModeAndValues +void +ColorSlider::SetModeAndValues(selected_color_mode mode, + float value1, float value2) +{ + float R(0), G(0), B(0); + float h(0), s(0), v(0); + + fBgBitmap->Lock(); + + switch (fMode) { + + case R_SELECTED: { + R = 255 - Value(); + G = round(fFixedValue1 * 255.0); + B = round(fFixedValue2 * 255.0); + }; break; + + case G_SELECTED: { + R = round(fFixedValue1 * 255.0); + G = 255 - Value(); + B = round(fFixedValue2 * 255.0); + }; break; + + case B_SELECTED: { + R = round(fFixedValue1 * 255.0); + G = round(fFixedValue2 * 255.0); + B = 255 - Value(); + }; break; + + case H_SELECTED: { + h = (1.0 - (float)Value()/255.0)*6.0; + s = fFixedValue1; + v = fFixedValue2; + }; break; + + case S_SELECTED: { + h = fFixedValue1; + s = 1.0 - (float)Value()/255.0; + v = fFixedValue2; + }; break; + + case V_SELECTED: { + h = fFixedValue1; + s = fFixedValue2; + v = 1.0 - (float)Value()/255.0; + }; break; + } + + if (fMode & (H_SELECTED|S_SELECTED|V_SELECTED) ) { + HSV_to_RGB(h, s, v, R, G, B); + R*=255.0; G*=255.0; B*=255.0; + } + + rgb_color color = { round(R), round(G), round(B), 255 }; + + fMode = mode; + SetOtherValues(value1, value2); + fBgBitmap->Unlock(); + + SetMarkerToColor( color ); + Update(2); +} + +// SetOtherValues +void +ColorSlider::SetOtherValues(float value1, float value2) +{ + fFixedValue1 = value1; + fFixedValue2 = value2; + + if (fMode != H_SELECTED) { + Update(2); + } +} + +// GetOtherValues +void +ColorSlider::GetOtherValues(float* value1, float* value2) const +{ + if (value1 && value2) { + *value1 = fFixedValue1; + *value2 = fFixedValue2; + } +} + +// SetMarkerToColor +void +ColorSlider::SetMarkerToColor(rgb_color color) +{ + float h, s, v; + if (fMode & (H_SELECTED | S_SELECTED | V_SELECTED)) { + RGB_to_HSV((float)color.red / 255.0, + (float)color.green / 255.0, + (float)color.blue / 255.0, + h, s, v); + } + + switch (fMode) { + + case R_SELECTED: { + SetValue( 255 - color.red ); + } break; + + case G_SELECTED: { + SetValue( 255 - color.green ); + } break; + + case B_SELECTED: { + SetValue( 255 - color.blue ); + } break; + + case H_SELECTED: { + SetValue( 255.0 - round(h / 6.0 * 255.0) ); + } break; + + case S_SELECTED: { + SetValue( 255.0 - round(s * 255.0) ); + } break; + + case V_SELECTED: { + SetValue( 255.0 - round(v * 255.0) ); + } break; + + } +} + +// _UpdateThread +int32 +ColorSlider::_UpdateThread(void* data) +{ + // initializing + ColorSlider* colorSlider = (ColorSlider*)data; + + bool looperLocked = colorSlider->LockLooper(); + + port_id port = colorSlider->fUpdatePort; + orientation orient = colorSlider->fOrientation; + + if (looperLocked) + colorSlider->UnlockLooper(); + + float h, s, v, r, g, b; + int R, G, B; + + // drawing + + int32 msg_code; + char msg_buffer; + + while (true) { + + port_info info; + + do { + + read_port(port, &msg_code, &msg_buffer, sizeof(msg_buffer)); + get_port_info(port, &info); + + } while (info.queue_count); + + if (colorSlider->LockLooper()) { + + uint colormode = colorSlider->fMode; + float fixedvalue1 = colorSlider->fFixedValue1; + float fixedvalue2 = colorSlider->fFixedValue2; + + BBitmap* bitmap = colorSlider->fBgBitmap; + BView* view = colorSlider->fBgView; + + bitmap->Lock(); + + colorSlider->UnlockLooper(); + + view->BeginLineArray(256); + + switch (colormode) { + + case R_SELECTED: { + G = round(fixedvalue1 * 255); + B = round(fixedvalue2 * 255); + for (int R = 0; R < 256; ++R) { + _DrawColorLineY( view, R, R, G, B ); + } + }; break; + + case G_SELECTED: { + R = round(fixedvalue1 * 255); + B = round(fixedvalue2 * 255); + for (int G = 0; G < 256; ++G) { + _DrawColorLineY( view, G, R, G, B ); + } + }; break; + + case B_SELECTED: { + R = round(fixedvalue1 * 255); + G = round(fixedvalue2 * 255); + for (int B = 0; B < 256; ++B) { + _DrawColorLineY( view, B, R, G, B ); + } + }; break; + + case H_SELECTED: { + s = 1.0;//fixedvalue1; + v = 1.0;//fixedvalue2; + if (orient == B_VERTICAL) { + for (int y = 0; y < 256; ++y) { + HSV_to_RGB( (float)y*6.0/255.0, s, v, r, g, b ); + _DrawColorLineY( view, y, r*255, g*255, b*255 ); + } + } else { + for (int x = 0; x < 256; ++x) { + HSV_to_RGB( (float)x*6.0/255.0, s, v, r, g, b ); + _DrawColorLineX( view, x, r*255, g*255, b*255 ); + } + } + }; break; + + case S_SELECTED: { + h = fixedvalue1; + v = 1.0;//fixedvalue2; + for (int y = 0; y < 256; ++y) { + HSV_to_RGB( h, (float)y/255, v, r, g, b ); + _DrawColorLineY( view, y, r*255, g*255, b*255 ); + } + }; break; + + case V_SELECTED: { + h = fixedvalue1; + s = 1.0;//fixedvalue2; + for (int y = 0; y < 256; ++y) { + HSV_to_RGB( h, s, (float)y/255, r, g, b ); + _DrawColorLineY( view, y, r*255, g*255, b*255 ); + } + }; break; + } + + view->EndLineArray(); + view->Sync(); + bitmap->Unlock(); + + if (colorSlider->LockLooper()) { + colorSlider->Update(1); + colorSlider->UnlockLooper(); + } + } + } +} + +// _DrawColorLineY +void +ColorSlider::_DrawColorLineY(BView *view, float y, + int r, int g, int b) +{ + rgb_color color = { r, g, b, 255 }; + y = 255.0 - y; + view->AddLine( BPoint(8.0, y + 5.0), BPoint(27.0, y + 5.0), color ); +} + +// _DrawColorLineX +void +ColorSlider::_DrawColorLineX(BView *view, float x, + int r, int g, int b) +{ + rgb_color color = { r, g, b, 255 }; + BRect bounds(view->Bounds()); + x = (255.0 - x) * (bounds.Width() - 2.0) / 255.0 + 2.0; + view->AddLine( BPoint(x, bounds.top + 2.0), BPoint(x, bounds.bottom - 2.0), color ); +} + +// _TrackMouse +void +ColorSlider::_TrackMouse(BPoint where) +{ + if (fOrientation == B_VERTICAL) { + SetValue((int)where.y - 2); + } else { + BRect b(Bounds()); + SetValue((int)(((where.x - 2.0) / b.Width()) * 255.0)); + } + Invoke(); +} diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorSlider.h b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorSlider.h new file mode 100644 index 0000000000..341d1a018f --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/ColorSlider.h @@ -0,0 +1,98 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + * Copyright 2002-2006, Stephan Aßmus + * All rights reserved. + * + */ + +#ifndef _COLOR_SLIDER_H +#define _COLOR_SLIDER_H + +#include "ColorPickerDefs.h" + +#include + +#if LIB_LAYOUT +# include +#endif + +#include "selected_color_mode.h" + +#define MSG_COLOR_SLIDER 'ColS' + +class BBitmap; + +class ColorSlider : + #if LIB_LAYOUT + public MView, + #endif + public BControl { + +public: + ColorSlider(BPoint offset_point, + selected_color_mode mode, + float value1, float value2, + orientation dir = B_VERTICAL); + virtual ~ColorSlider(); + + #if LIB_LAYOUT + // MView + virtual minimax layoutprefs(); + virtual BRect layout(BRect frame); + #endif + + // BControl + virtual void AttachedToWindow(); + + virtual status_t Invoke(BMessage* message = NULL); + + virtual void Draw(BRect updateRect); + virtual void FrameResized(float width, float height); + + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 code, + const BMessage* dragMessage); + + virtual void SetValue(int32 value); + + // ColorSlider + void Update(int depth); + + bool IsTracking() const + { return fMouseDown; } + + void SetModeAndValues(selected_color_mode mode, + float value1, float value2); + void SetOtherValues(float value1, float value2); + void GetOtherValues(float* value1, float* value2) const; + + void SetMarkerToColor( rgb_color color ); + +// inline void _DrawColorLineY( float y, int r, int g, int b); +private: + + static int32 _UpdateThread(void* cookie); + static inline void _DrawColorLineY(BView* view, float y, + int r, int g, int b); + static inline void _DrawColorLineX(BView* view, float x, + int r, int g, int b); + void _TrackMouse(BPoint where); + + selected_color_mode fMode; + float fFixedValue1; + float fFixedValue2; + + bool fMouseDown; + + BBitmap* fBgBitmap; + BView* fBgView; + + thread_id fUpdateThread; + port_id fUpdatePort; + + orientation fOrientation; +}; + +#endif diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/LICENSE b/src/apps/icon-o-matic/generic/gui/panel/color_picker/LICENSE new file mode 100644 index 0000000000..71339f0b5c --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/LICENSE @@ -0,0 +1,16 @@ +License +You may use this source code without charge in your own projects, as long as you create a BeOS program. If you want to create something else, please contact the author about an individual license. + +If you re-release this source code or parts of it, you must add this LICENSE file. + +All graphics, especially the icon or brands are copyrighted by the author and may not be used in any form without the author's consent. + +Author / contact +Werner Freytag +Neurieder Str. 8 +82152 Martinsried +Germany + +e-mail: info@pecora.de +visit: http://www.pecora.de + diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/rgb_hsv.h b/src/apps/icon-o-matic/generic/gui/panel/color_picker/rgb_hsv.h new file mode 100644 index 0000000000..ce45770037 --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/rgb_hsv.h @@ -0,0 +1,94 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + */ + +#ifndef CONVERT_RGB_HSV_H +#define CONVERT_RGB_HSV_H + +#define RETURN_HSV(h, s, v) { H = h; S = s; V = v; return; } +#define RETURN_RGB(r, g, b) { R = r; G = g; B = b; return; } + +#include + +#define UNDEFINED 0 + +inline void +RGB_to_HSV(float R, float G, float B, float& H, float& S, float& V) +{ + // RGB are each on [0, 1]. S and max are returned on [0, 1] and H is + // returned on [0, 6]. Eminception: H is returned UNDEFINED if S==0. + + float min, max; + + if (R > G) { + if (R > B) { + max = R; + min = G > B ? B : G; + } + else { + max = B; + min = G; + } + } + else { + if (G > B) { + max = G; + min = R > B ? B : R; + } + else { + max = B; + min = R; + } + } + + if (max == min) RETURN_HSV(UNDEFINED, 0, max); + + float dist = max - min; + + float f = (R == min) ? G - B : ((G == min) ? B - R : R - G); + float i = (R == min) ? 3 : ((G == min) ? 5 : 1); + float h = i - f / dist; + + while (h >= 6.0) h -= 6.0; + + RETURN_HSV(h, dist/max, max); + +} + +inline void +HSV_to_RGB(float h, float s, float v, float& R, float& G, float& B) +{ + // H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1]. + // RGB are each returned on [0, 1]. + + int i = (int)floor(h); + + float f = h - i; + + if ( !(i & 1) ) f = 1 - f; // if i is even + + float m = v * (1 - s); + + float n = v * (1 - s * f); + + switch (i) { + + case 6: + + case 0: RETURN_RGB(v, n, m); + + case 1: RETURN_RGB(n, v, m); + + case 2: RETURN_RGB(m, v, n) + + case 3: RETURN_RGB(m, n, v); + + case 4: RETURN_RGB(n, m, v); + + case 5: RETURN_RGB(v, m, n); + + } +} + +#endif // CONVERT_RGB_HSV_H diff --git a/src/apps/icon-o-matic/generic/gui/panel/color_picker/selected_color_mode.h b/src/apps/icon-o-matic/generic/gui/panel/color_picker/selected_color_mode.h new file mode 100644 index 0000000000..e4d06638b3 --- /dev/null +++ b/src/apps/icon-o-matic/generic/gui/panel/color_picker/selected_color_mode.h @@ -0,0 +1,18 @@ +/* + * Copyright 2001 Werner Freytag - please read to the LICENSE file + * + */ + +#ifndef _SELECTED_COLOR_MODE_H +#define _SELECTED_COLOR_MODE_H + +enum selected_color_mode { + R_SELECTED = 0x01, + G_SELECTED = 0x02, + B_SELECTED = 0x04, + H_SELECTED = 0x10, + S_SELECTED = 0x20, + V_SELECTED = 0x40 +}; + +#endif // _SELECTED_COLOR_MODE_H diff --git a/src/apps/icon-o-matic/generic/support/support_ui.cpp b/src/apps/icon-o-matic/generic/support/support_ui.cpp index 8e53364757..5ef1297792 100644 --- a/src/apps/icon-o-matic/generic/support/support_ui.cpp +++ b/src/apps/icon-o-matic/generic/support/support_ui.cpp @@ -6,7 +6,7 @@ * Stephan Aßmus */ -#include "support.h" +#include "support_ui.h" #include #include @@ -21,8 +21,6 @@ #include #include -#include - // stroke_frame void stroke_frame(BView* v, BRect r, rgb_color left, rgb_color top, @@ -42,20 +40,6 @@ stroke_frame(BView* v, BRect r, rgb_color left, rgb_color top, } } -// vertical_space -Space* -vertical_space() -{ - return new Space(minimax(0.0, 3.0, 10000.0, 3.0, 1.0)); -} - -// horizontal_space -Space* -horizontal_space() -{ - return new Space(minimax(3.0, 0.0, 3.0, 10000.0, 1.0)); -} - // store_color_in_message status_t store_color_in_message(BMessage* message, rgb_color color) diff --git a/src/apps/icon-o-matic/generic/support/support_ui.h b/src/apps/icon-o-matic/generic/support/support_ui.h index 9623f8206d..0865ab2c03 100644 --- a/src/apps/icon-o-matic/generic/support/support_ui.h +++ b/src/apps/icon-o-matic/generic/support/support_ui.h @@ -20,7 +20,6 @@ class BPositionIO; class BString; class BView; class BWindow; -class Space; // looper of view must be locked! void stroke_frame(BView* view, BRect frame, @@ -28,9 +27,6 @@ void stroke_frame(BView* view, BRect frame, rgb_color right, rgb_color bottom); -Space* vertical_space(); -Space* horizontal_space(); - status_t store_color_in_message(BMessage* message, rgb_color color); status_t restore_color_from_message(const BMessage* message, rgb_color& color, int32 index = 0);