2006-01-16 22:02:54 +01:00
|
|
|
// Copyright (c) 2005, Niels Martin Hansen
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer.
|
|
|
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
|
|
// and/or other materials provided with the distribution.
|
|
|
|
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
|
|
// may be used to endorse or promote products derived from this software
|
|
|
|
// without specific prior written permission.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
|
|
|
/// @file dialog_colorpicker.cpp
|
|
|
|
/// @brief Custom colour-selection dialogue box
|
|
|
|
/// @ingroup tools_ui
|
|
|
|
///
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2009-01-04 07:31:48 +01:00
|
|
|
#include "config.h"
|
|
|
|
|
2009-09-10 15:06:40 +02:00
|
|
|
#ifndef AGI_PRE
|
|
|
|
#include <stdio.h>
|
2010-06-09 10:14:50 +02:00
|
|
|
#include <vector>
|
2009-09-10 15:06:40 +02:00
|
|
|
|
2010-06-09 10:14:50 +02:00
|
|
|
#include <wx/bitmap.h>
|
|
|
|
#include <wx/button.h>
|
|
|
|
#include <wx/choice.h>
|
2009-09-10 15:06:40 +02:00
|
|
|
#include <wx/clipbrd.h>
|
|
|
|
#include <wx/dataobj.h>
|
2007-09-12 01:22:26 +02:00
|
|
|
#include <wx/dcclient.h>
|
|
|
|
#include <wx/dcmemory.h>
|
|
|
|
#include <wx/dcscreen.h>
|
2010-06-09 10:14:50 +02:00
|
|
|
#include <wx/dialog.h>
|
2009-09-10 15:06:40 +02:00
|
|
|
#include <wx/event.h>
|
|
|
|
#include <wx/gbsizer.h>
|
|
|
|
#include <wx/image.h>
|
2011-01-11 18:22:44 +01:00
|
|
|
#include <wx/rawbmp.h>
|
2007-09-12 01:22:26 +02:00
|
|
|
#include <wx/settings.h>
|
2009-09-10 15:06:40 +02:00
|
|
|
#include <wx/sizer.h>
|
2010-06-09 10:14:50 +02:00
|
|
|
#include <wx/spinctrl.h>
|
|
|
|
#include <wx/statbmp.h>
|
2009-09-10 15:06:40 +02:00
|
|
|
#include <wx/statbox.h>
|
|
|
|
#include <wx/stattext.h>
|
2010-06-09 10:14:50 +02:00
|
|
|
#include <wx/textctrl.h>
|
2009-09-10 15:06:40 +02:00
|
|
|
#include <wx/tokenzr.h>
|
|
|
|
#endif
|
|
|
|
|
2011-07-27 07:36:30 +02:00
|
|
|
#include <libaegisub/scoped_ptr.h>
|
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
#include "ass_style.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "colorspace.h"
|
2010-05-21 03:13:36 +02:00
|
|
|
#include "compat.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "dialog_colorpicker.h"
|
2008-01-13 23:06:04 +01:00
|
|
|
#include "help_button.h"
|
2009-07-24 02:08:25 +02:00
|
|
|
#include "libresrc/libresrc.h"
|
2010-05-21 03:13:36 +02:00
|
|
|
#include "main.h"
|
2011-07-27 07:36:30 +02:00
|
|
|
#include "persist_location.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "utils.h"
|
2008-07-16 03:29:36 +02:00
|
|
|
|
2012-06-12 05:13:55 +02:00
|
|
|
#ifdef __WXMAC__
|
|
|
|
#include <ApplicationServices/ApplicationServices.h>
|
|
|
|
#endif
|
|
|
|
|
2010-06-09 10:14:50 +02:00
|
|
|
class ColorPickerSpectrum : public wxControl {
|
|
|
|
public:
|
|
|
|
enum PickerDirection {
|
|
|
|
HorzVert,
|
|
|
|
Horz,
|
|
|
|
Vert
|
|
|
|
};
|
|
|
|
private:
|
2011-10-17 19:52:49 +02:00
|
|
|
int x;
|
|
|
|
int y;
|
2010-06-09 10:14:50 +02:00
|
|
|
|
|
|
|
wxBitmap *background;
|
|
|
|
PickerDirection direction;
|
|
|
|
|
|
|
|
void OnPaint(wxPaintEvent &evt);
|
|
|
|
void OnMouse(wxMouseEvent &evt);
|
|
|
|
|
2012-04-06 17:51:07 +02:00
|
|
|
bool AcceptsFocusFromKeyboard() const { return false; }
|
|
|
|
|
2010-06-09 10:14:50 +02:00
|
|
|
public:
|
2011-10-17 19:52:49 +02:00
|
|
|
ColorPickerSpectrum(wxWindow *parent, PickerDirection direction, wxSize size);
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
int GetX() const { return x; }
|
|
|
|
int GetY() const { return y; }
|
2010-06-09 10:14:50 +02:00
|
|
|
void SetXY(int xx, int yy);
|
2010-06-18 09:14:11 +02:00
|
|
|
void SetBackground(wxBitmap *new_background, bool force = false);
|
2010-06-09 10:14:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/// @class ColorPickerRecent
|
2012-10-26 16:09:14 +02:00
|
|
|
/// @brief A grid of recently used colors which can be selected by clicking on them
|
2010-06-09 10:14:50 +02:00
|
|
|
class ColorPickerRecent : public wxControl {
|
2011-10-17 19:52:49 +02:00
|
|
|
int rows; ///< Number of rows of colors
|
|
|
|
int cols; ///< Number of cols of colors
|
|
|
|
int cellsize; ///< Width/Height of each cell
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// The colors currently displayed in the control
|
2012-10-26 16:09:14 +02:00
|
|
|
std::vector<agi::Color> colors;
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// Does the background need to be regenerated?
|
2010-06-09 10:14:50 +02:00
|
|
|
bool background_valid;
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// Bitmap storing the cached background
|
2010-06-09 10:14:50 +02:00
|
|
|
wxBitmap background;
|
|
|
|
|
|
|
|
void OnClick(wxMouseEvent &evt);
|
|
|
|
void OnPaint(wxPaintEvent &evt);
|
|
|
|
void OnSize(wxSizeEvent &evt);
|
|
|
|
|
2012-04-06 17:51:07 +02:00
|
|
|
bool AcceptsFocusFromKeyboard() const { return false; }
|
|
|
|
|
2010-06-09 10:14:50 +02:00
|
|
|
public:
|
2011-10-17 19:52:49 +02:00
|
|
|
ColorPickerRecent(wxWindow *parent, int cols, int rows, int cellsize);
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
/// Load the colors to show
|
|
|
|
void Load(std::vector<agi::Color> const& recent_colors);
|
|
|
|
|
|
|
|
/// Get the list of recent colors
|
|
|
|
std::vector<agi::Color> Save() const;
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// Add a color to the beginning of the recent list
|
2012-10-26 16:09:14 +02:00
|
|
|
void AddColor(agi::Color color);
|
2010-06-09 10:14:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class ColorPickerScreenDropper : public wxControl {
|
|
|
|
wxBitmap capture;
|
|
|
|
|
|
|
|
int resx, resy;
|
|
|
|
int magnification;
|
|
|
|
|
|
|
|
void OnMouse(wxMouseEvent &evt);
|
|
|
|
void OnPaint(wxPaintEvent &evt);
|
|
|
|
|
2012-04-06 17:51:07 +02:00
|
|
|
bool AcceptsFocusFromKeyboard() const { return false; }
|
|
|
|
|
2010-06-09 10:14:50 +02:00
|
|
|
public:
|
2011-10-17 19:52:49 +02:00
|
|
|
ColorPickerScreenDropper(wxWindow *parent, int resx, int resy, int magnification);
|
2010-06-09 10:14:50 +02:00
|
|
|
|
|
|
|
void DropFromScreenXY(int x, int y);
|
|
|
|
};
|
|
|
|
|
|
|
|
class DialogColorPicker : public wxDialog {
|
2011-07-27 07:36:30 +02:00
|
|
|
agi::scoped_ptr<PersistLocation> persist;
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
agi::Color cur_color; ///< Currently selected colour
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
bool spectrum_dirty; ///< Does the spectrum image need to be regenerated?
|
|
|
|
ColorPickerSpectrum *spectrum; ///< The 2D color spectrum
|
|
|
|
ColorPickerSpectrum *slider; ///< The 1D slider for the color component not in the slider
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxChoice *colorspace_choice; ///< The dropdown list to select colorspaces
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2011-07-27 07:36:30 +02:00
|
|
|
static const int slider_width = 10; ///< width in pixels of the color slider control
|
2010-06-09 10:14:50 +02:00
|
|
|
|
|
|
|
wxSpinCtrl *rgb_input[3];
|
2011-10-17 19:52:49 +02:00
|
|
|
wxBitmap *rgb_spectrum[3]; ///< x/y spectrum bitmap where color "i" is excluded from
|
|
|
|
wxBitmap *rgb_slider[3]; ///< z spectrum for color "i"
|
|
|
|
|
2010-06-09 10:14:50 +02:00
|
|
|
wxSpinCtrl *hsl_input[3];
|
2011-10-17 19:52:49 +02:00
|
|
|
wxBitmap *hsl_spectrum; ///< h/s spectrum
|
|
|
|
wxBitmap *hsl_slider; ///< l spectrum
|
|
|
|
|
2010-06-09 10:14:50 +02:00
|
|
|
wxSpinCtrl *hsv_input[3];
|
2011-10-17 19:52:49 +02:00
|
|
|
wxBitmap *hsv_spectrum; ///< s/v spectrum
|
|
|
|
wxBitmap *hsv_slider; ///< h spectrum
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxTextCtrl *ass_input;
|
|
|
|
wxTextCtrl *html_input;
|
|
|
|
|
|
|
|
/// The eyedropper is set to a blank icon when it's clicked, so store its normal bitmap
|
2010-06-09 10:14:50 +02:00
|
|
|
wxBitmap eyedropper_bitmap;
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// The point where the eyedropper was click, used to make it possible to either
|
|
|
|
/// click the eyedropper or drag the eyedropper
|
2010-06-09 10:14:50 +02:00
|
|
|
wxPoint eyedropper_grab_point;
|
|
|
|
|
|
|
|
/// DOCME
|
|
|
|
bool eyedropper_is_grabbed;
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxStaticBitmap *preview_box; ///< A box which simply shows the current color
|
|
|
|
ColorPickerRecent *recent_box; ///< A grid of recently used colors
|
2010-06-09 10:14:50 +02:00
|
|
|
|
|
|
|
/// DOCME
|
|
|
|
ColorPickerScreenDropper *screen_dropper;
|
|
|
|
|
|
|
|
/// DOCME
|
|
|
|
wxStaticBitmap *screen_dropper_icon;
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// Update all other controls as a result of modifying an RGB control
|
|
|
|
void UpdateFromRGB(bool dirty = true);
|
|
|
|
/// Update all other controls as a result of modifying an HSL control
|
|
|
|
void UpdateFromHSL(bool dirty = true);
|
|
|
|
/// Update all other controls as a result of modifying an HSV control
|
|
|
|
void UpdateFromHSV(bool dirty = true);
|
|
|
|
/// Update all other controls as a result of modifying the ASS format control
|
2012-10-12 03:52:36 +02:00
|
|
|
void UpdateFromAss();
|
2011-10-17 19:52:49 +02:00
|
|
|
/// Update all other controls as a result of modifying the HTML format control
|
|
|
|
void UpdateFromHTML();
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
void SetRGB(agi::Color new_color);
|
2011-10-17 19:52:49 +02:00
|
|
|
void SetHSL(unsigned char r, unsigned char g, unsigned char b);
|
|
|
|
void SetHSV(unsigned char r, unsigned char g, unsigned char b);
|
|
|
|
|
|
|
|
/// Redraw the spectrum display
|
|
|
|
void UpdateSpectrumDisplay();
|
2010-06-09 10:14:50 +02:00
|
|
|
|
|
|
|
wxBitmap *MakeGBSpectrum();
|
|
|
|
wxBitmap *MakeRBSpectrum();
|
|
|
|
wxBitmap *MakeRGSpectrum();
|
|
|
|
wxBitmap *MakeHSSpectrum();
|
|
|
|
wxBitmap *MakeSVSpectrum();
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// Constructor helper function for making the color input box sizers
|
|
|
|
template<int N, class Control>
|
|
|
|
wxSizer *MakeColorInputSizer(wxString (&labels)[N], Control *(&inputs)[N]);
|
|
|
|
|
2010-06-09 10:14:50 +02:00
|
|
|
void OnChangeMode(wxCommandEvent &evt);
|
|
|
|
void OnSpectrumChange(wxCommandEvent &evt);
|
|
|
|
void OnSliderChange(wxCommandEvent &evt);
|
2012-10-26 16:09:14 +02:00
|
|
|
void OnRecentSelect(wxThreadEvent &evt); // also handles dropper pick
|
2010-06-09 10:14:50 +02:00
|
|
|
void OnDropperMouse(wxMouseEvent &evt);
|
|
|
|
void OnMouse(wxMouseEvent &evt);
|
2011-12-22 22:26:30 +01:00
|
|
|
void OnCaptureLost(wxMouseCaptureLostEvent&);
|
2010-06-09 10:14:50 +02:00
|
|
|
|
2012-09-25 01:35:27 +02:00
|
|
|
std::function<void (agi::Color)> callback;
|
2010-06-09 10:14:50 +02:00
|
|
|
|
|
|
|
public:
|
2012-09-25 01:35:27 +02:00
|
|
|
DialogColorPicker(wxWindow *parent, agi::Color initial_color, std::function<void (agi::Color)> callback);
|
2010-06-09 10:14:50 +02:00
|
|
|
~DialogColorPicker();
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
void SetColor(agi::Color new_color);
|
|
|
|
agi::Color GetColor();
|
2010-06-09 10:14:50 +02:00
|
|
|
};
|
|
|
|
|
2008-11-24 15:05:46 +01:00
|
|
|
static const int spectrum_horz_vert_arrow_size = 4;
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
ColorPickerSpectrum::ColorPickerSpectrum(wxWindow *parent, PickerDirection direction, wxSize size)
|
|
|
|
: wxControl(parent, -1, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE)
|
|
|
|
, x(-1)
|
|
|
|
, y(-1)
|
|
|
|
, background(0)
|
|
|
|
, direction(direction)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
size.x += 2;
|
|
|
|
size.y += 2;
|
2008-11-24 15:05:46 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
if (direction == Vert) size.x += spectrum_horz_vert_arrow_size + 1;
|
|
|
|
if (direction == Horz) size.y += spectrum_horz_vert_arrow_size + 1;
|
2008-11-24 15:05:46 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
SetClientSize(size);
|
2008-11-24 15:05:46 +01:00
|
|
|
SetMinSize(GetSize());
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
Bind(wxEVT_LEFT_DOWN, &ColorPickerSpectrum::OnMouse, this);
|
|
|
|
Bind(wxEVT_LEFT_UP, &ColorPickerSpectrum::OnMouse, this);
|
|
|
|
Bind(wxEVT_MOTION, &ColorPickerSpectrum::OnMouse, this);
|
|
|
|
Bind(wxEVT_PAINT, &ColorPickerSpectrum::OnPaint, this);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColorPickerSpectrum::SetXY(int xx, int yy)
|
|
|
|
{
|
2010-06-11 04:25:23 +02:00
|
|
|
if (x != xx || y != yy) {
|
|
|
|
x = xx;
|
|
|
|
y = yy;
|
|
|
|
Refresh(false);
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2010-06-18 09:14:11 +02:00
|
|
|
/// @brief Set the background image for this spectrum
|
|
|
|
/// @param new_background New background image
|
|
|
|
/// @param force Repaint even if it appears to be the same image
|
|
|
|
void ColorPickerSpectrum::SetBackground(wxBitmap *new_background, bool force)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2010-06-18 09:14:11 +02:00
|
|
|
if (background == new_background && !force) return;
|
2006-01-16 22:02:54 +01:00
|
|
|
background = new_background;
|
2010-06-11 04:25:23 +02:00
|
|
|
Refresh(false);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxDEFINE_EVENT(EVT_SPECTRUM_CHANGE, wxCommandEvent);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void ColorPickerSpectrum::OnPaint(wxPaintEvent &)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
|
|
|
if (!background) return;
|
|
|
|
|
2010-06-11 04:25:23 +02:00
|
|
|
int height = background->GetHeight();
|
|
|
|
int width = background->GetWidth();
|
2006-01-16 22:02:54 +01:00
|
|
|
wxPaintDC dc(this);
|
|
|
|
|
|
|
|
wxMemoryDC memdc;
|
|
|
|
memdc.SelectObject(*background);
|
2010-06-11 04:25:23 +02:00
|
|
|
dc.Blit(1, 1, width, height, &memdc, 0, 0);
|
2008-11-24 15:05:46 +01:00
|
|
|
|
|
|
|
wxPoint arrow[3];
|
2010-06-11 04:25:23 +02:00
|
|
|
wxRect arrow_box;
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2010-06-11 04:25:23 +02:00
|
|
|
wxPen invpen(*wxWHITE, 3);
|
|
|
|
invpen.SetCap(wxCAP_BUTT);
|
2006-01-16 22:02:54 +01:00
|
|
|
dc.SetLogicalFunction(wxXOR);
|
2008-11-24 15:05:46 +01:00
|
|
|
dc.SetPen(invpen);
|
2010-06-11 04:25:23 +02:00
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
switch (direction) {
|
|
|
|
case HorzVert:
|
|
|
|
// Make a little cross
|
2008-11-24 15:05:46 +01:00
|
|
|
dc.DrawLine(x-4, y+1, x+7, y+1);
|
|
|
|
dc.DrawLine(x+1, y-4, x+1, y+7);
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
|
|
|
case Horz:
|
|
|
|
// Make a vertical line stretching all the way across
|
2010-06-11 04:25:23 +02:00
|
|
|
dc.DrawLine(x+1, 1, x+1, height+1);
|
2008-11-24 15:05:46 +01:00
|
|
|
// Points for arrow
|
2010-06-11 04:25:23 +02:00
|
|
|
arrow[0] = wxPoint(x+1, height+2);
|
|
|
|
arrow[1] = wxPoint(x+1-spectrum_horz_vert_arrow_size, height+2+spectrum_horz_vert_arrow_size);
|
|
|
|
arrow[2] = wxPoint(x+1+spectrum_horz_vert_arrow_size, height+2+spectrum_horz_vert_arrow_size);
|
|
|
|
|
|
|
|
arrow_box.SetLeft(0);
|
|
|
|
arrow_box.SetTop(height + 2);
|
|
|
|
arrow_box.SetRight(width + 1 + spectrum_horz_vert_arrow_size);
|
|
|
|
arrow_box.SetBottom(height + 2 + spectrum_horz_vert_arrow_size);
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
|
|
|
case Vert:
|
|
|
|
// Make a horizontal line stretching all the way across
|
2010-06-11 04:25:23 +02:00
|
|
|
dc.DrawLine(1, y+1, width+1, y+1);
|
2008-11-24 15:05:46 +01:00
|
|
|
// Points for arrow
|
2010-06-11 04:25:23 +02:00
|
|
|
arrow[0] = wxPoint(width+2, y+1);
|
|
|
|
arrow[1] = wxPoint(width+2+spectrum_horz_vert_arrow_size, y+1-spectrum_horz_vert_arrow_size);
|
|
|
|
arrow[2] = wxPoint(width+2+spectrum_horz_vert_arrow_size, y+1+spectrum_horz_vert_arrow_size);
|
|
|
|
|
|
|
|
arrow_box.SetLeft(width + 2);
|
|
|
|
arrow_box.SetTop(0);
|
|
|
|
arrow_box.SetRight(width + 2 + spectrum_horz_vert_arrow_size);
|
|
|
|
arrow_box.SetBottom(height + 1 + spectrum_horz_vert_arrow_size);
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
|
|
|
}
|
2008-11-24 15:05:46 +01:00
|
|
|
|
|
|
|
if (direction == Horz || direction == Vert) {
|
2010-06-11 04:25:23 +02:00
|
|
|
wxBrush bgBrush;
|
|
|
|
bgBrush.SetColour(GetBackgroundColour());
|
2008-11-24 15:05:46 +01:00
|
|
|
dc.SetLogicalFunction(wxCOPY);
|
|
|
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
2010-06-11 04:25:23 +02:00
|
|
|
dc.SetBrush(bgBrush);
|
|
|
|
dc.DrawRectangle(arrow_box);
|
|
|
|
|
|
|
|
// Arrow pointing at current point
|
2008-11-24 15:05:46 +01:00
|
|
|
dc.SetBrush(*wxBLACK_BRUSH);
|
|
|
|
dc.DrawPolygon(3, arrow);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Border around the spectrum
|
2010-06-11 04:25:23 +02:00
|
|
|
wxPen blkpen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), 1);
|
|
|
|
blkpen.SetCap(wxCAP_BUTT);
|
|
|
|
|
2008-11-24 15:05:46 +01:00
|
|
|
dc.SetLogicalFunction(wxCOPY);
|
|
|
|
dc.SetPen(blkpen);
|
|
|
|
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
|
|
|
dc.DrawRectangle(0, 0, background->GetWidth()+2, background->GetHeight()+2);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ColorPickerSpectrum::OnMouse(wxMouseEvent &evt)
|
|
|
|
{
|
|
|
|
evt.Skip();
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
// We only care about mouse move events during a drag
|
|
|
|
if (evt.Moving())
|
2006-01-16 22:02:54 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (evt.LeftDown()) {
|
|
|
|
CaptureMouse();
|
2007-07-05 00:23:52 +02:00
|
|
|
SetCursor(wxCursor(wxCURSOR_BLANK));
|
2011-10-17 19:52:49 +02:00
|
|
|
}
|
|
|
|
else if (evt.LeftUp() && HasCapture()) {
|
2006-01-16 22:02:54 +01:00
|
|
|
ReleaseMouse();
|
2007-07-05 00:23:52 +02:00
|
|
|
SetCursor(wxNullCursor);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (evt.LeftDown() || (HasCapture() && evt.LeftIsDown())) {
|
2011-10-17 19:52:49 +02:00
|
|
|
int newx = mid(0, evt.GetX(), GetClientSize().x - 1);
|
|
|
|
int newy = mid(0, evt.GetY(), GetClientSize().y - 1);
|
2010-06-11 04:25:23 +02:00
|
|
|
SetXY(newx, newy);
|
2011-10-17 19:52:49 +02:00
|
|
|
wxCommandEvent evt2(EVT_SPECTRUM_CHANGE, GetId());
|
2006-01-16 22:02:54 +01:00
|
|
|
AddPendingEvent(evt2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
#ifdef WIN32
|
|
|
|
#define STATIC_BORDER_FLAG wxSTATIC_BORDER
|
|
|
|
#else
|
|
|
|
#define STATIC_BORDER_FLAG wxSIMPLE_BORDER
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ColorPickerRecent::ColorPickerRecent(wxWindow *parent, int cols, int rows, int cellsize)
|
|
|
|
: wxControl(parent, -1, wxDefaultPosition, wxDefaultSize, STATIC_BORDER_FLAG)
|
|
|
|
, rows(rows)
|
|
|
|
, cols(cols)
|
|
|
|
, cellsize(cellsize)
|
2008-07-16 03:29:36 +02:00
|
|
|
, background_valid(false)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-10-26 16:09:14 +02:00
|
|
|
colors.resize(rows * cols);
|
2006-07-07 00:16:27 +02:00
|
|
|
SetClientSize(cols*cellsize, rows*cellsize);
|
|
|
|
SetMinSize(GetSize());
|
|
|
|
SetMaxSize(GetSize());
|
2007-07-05 00:23:52 +02:00
|
|
|
SetCursor(*wxCROSS_CURSOR);
|
2011-10-17 19:52:49 +02:00
|
|
|
|
|
|
|
Bind(wxEVT_PAINT, &ColorPickerRecent::OnPaint, this);
|
|
|
|
Bind(wxEVT_LEFT_DOWN, &ColorPickerRecent::OnClick, this);
|
|
|
|
Bind(wxEVT_SIZE, &ColorPickerRecent::OnSize, this);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
void ColorPickerRecent::Load(std::vector<agi::Color> const& recent_colors)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-10-26 16:09:14 +02:00
|
|
|
colors = recent_colors;
|
|
|
|
colors.resize(rows * cols);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
std::vector<agi::Color> ColorPickerRecent::Save() const
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-10-26 16:09:14 +02:00
|
|
|
return colors;
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
void ColorPickerRecent::AddColor(agi::Color color)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-11-04 04:53:03 +01:00
|
|
|
auto existing = find(colors.begin(), colors.end(), color);
|
2012-03-07 02:31:04 +01:00
|
|
|
if (existing != colors.end())
|
|
|
|
rotate(colors.begin(), existing, existing + 1);
|
2012-10-26 16:09:14 +02:00
|
|
|
else {
|
2012-03-07 02:31:04 +01:00
|
|
|
colors.insert(colors.begin(), color);
|
2012-10-26 16:09:14 +02:00
|
|
|
colors.pop_back();
|
|
|
|
}
|
2011-10-17 19:52:49 +02:00
|
|
|
|
2008-07-16 03:29:36 +02:00
|
|
|
background_valid = false;
|
2011-10-17 19:52:49 +02:00
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
Refresh(false);
|
|
|
|
}
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
wxDEFINE_EVENT(EVT_RECENT_SELECT, wxThreadEvent);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
void ColorPickerRecent::OnClick(wxMouseEvent &evt)
|
|
|
|
{
|
|
|
|
wxSize cs = GetClientSize();
|
2011-10-17 19:52:49 +02:00
|
|
|
int cx = evt.GetX() * cols / cs.x;
|
|
|
|
int cy = evt.GetY() * rows / cs.y;
|
2006-07-07 00:16:27 +02:00
|
|
|
if (cx < 0 || cx > cols || cy < 0 || cy > rows) return;
|
2011-10-17 19:52:49 +02:00
|
|
|
int i = cols*cy + cx;
|
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
if (i >= 0 && i < (int)colors.size()) {
|
2012-10-26 16:09:14 +02:00
|
|
|
wxThreadEvent evnt(EVT_RECENT_SELECT, GetId());
|
|
|
|
evnt.SetPayload(colors[i]);
|
2010-06-11 04:24:59 +02:00
|
|
|
AddPendingEvent(evnt);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void ColorPickerRecent::OnPaint(wxPaintEvent &)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2008-07-16 03:29:36 +02:00
|
|
|
wxPaintDC pdc(this);
|
|
|
|
PrepareDC(pdc);
|
|
|
|
|
|
|
|
if (!background_valid) {
|
|
|
|
wxSize sz = pdc.GetSize();
|
2011-10-17 19:52:49 +02:00
|
|
|
|
2008-07-16 03:29:36 +02:00
|
|
|
background = wxBitmap(sz.x, sz.y);
|
|
|
|
wxMemoryDC dc(background);
|
2011-10-17 19:52:49 +02:00
|
|
|
|
2008-07-16 03:29:36 +02:00
|
|
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
2011-10-17 19:52:49 +02:00
|
|
|
|
2008-07-16 03:29:36 +02:00
|
|
|
for (int cy = 0; cy < rows; cy++) {
|
|
|
|
for (int cx = 0; cx < cols; cx++) {
|
2011-10-17 19:52:49 +02:00
|
|
|
int x = cx * cellsize;
|
|
|
|
int y = cy * cellsize;
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
dc.SetBrush(wxBrush(to_wx(colors[cy * cols + cx])));
|
2008-07-16 03:29:36 +02:00
|
|
|
dc.DrawRectangle(x, y, x+cellsize, y+cellsize);
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
2011-10-17 19:52:49 +02:00
|
|
|
|
2008-07-16 03:29:36 +02:00
|
|
|
background_valid = true;
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
2011-10-17 19:52:49 +02:00
|
|
|
|
2008-07-16 03:29:36 +02:00
|
|
|
pdc.DrawBitmap(background, 0, 0, false);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void ColorPickerRecent::OnSize(wxSizeEvent &)
|
2006-07-07 00:16:27 +02:00
|
|
|
{
|
2008-07-16 03:29:36 +02:00
|
|
|
background_valid = false;
|
2006-07-07 00:16:27 +02:00
|
|
|
Refresh();
|
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
ColorPickerScreenDropper::ColorPickerScreenDropper(wxWindow *parent, int resx, int resy, int magnification)
|
|
|
|
: wxControl(parent, -1, wxDefaultPosition, wxDefaultSize, STATIC_BORDER_FLAG)
|
2012-06-17 22:22:38 +02:00
|
|
|
, capture(resx * magnification, resy * magnification, wxNativePixelFormat::BitsPerPixel)
|
2011-10-17 19:52:49 +02:00
|
|
|
, resx(resx)
|
|
|
|
, resy(resy)
|
|
|
|
, magnification(magnification)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
|
|
|
SetClientSize(resx*magnification, resy*magnification);
|
|
|
|
SetMinSize(GetSize());
|
|
|
|
SetMaxSize(GetSize());
|
2007-07-05 00:23:52 +02:00
|
|
|
SetCursor(*wxCROSS_CURSOR);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-06-12 05:13:55 +02:00
|
|
|
wxMemoryDC capdc(capture);
|
2006-01-16 22:02:54 +01:00
|
|
|
capdc.SetPen(*wxTRANSPARENT_PEN);
|
|
|
|
capdc.SetBrush(*wxWHITE_BRUSH);
|
2012-06-12 05:13:55 +02:00
|
|
|
capdc.DrawRectangle(0, 0, capture.GetWidth(), capture.GetHeight());
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
Bind(wxEVT_PAINT, &ColorPickerScreenDropper::OnPaint, this);
|
|
|
|
Bind(wxEVT_LEFT_DOWN, &ColorPickerScreenDropper::OnMouse, this);
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
wxDEFINE_EVENT(EVT_DROPPER_SELECT, wxThreadEvent);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
void ColorPickerScreenDropper::OnMouse(wxMouseEvent &evt)
|
|
|
|
{
|
2012-06-12 05:13:55 +02:00
|
|
|
int x = evt.GetX();
|
|
|
|
int y = evt.GetY();
|
|
|
|
|
|
|
|
if (x >= 0 && x < capture.GetWidth() && y >= 0 && y < capture.GetHeight()) {
|
|
|
|
wxNativePixelData pd(capture, wxRect(x, y, 1, 1));
|
|
|
|
wxNativePixelData::Iterator pdi(pd.GetPixels());
|
2012-10-26 16:09:14 +02:00
|
|
|
agi::Color color(pdi.Red(), pdi.Green(), pdi.Blue(), 0);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
wxThreadEvent evnt(EVT_DROPPER_SELECT, GetId());
|
|
|
|
evnt.SetPayload(color);
|
2011-10-17 19:52:49 +02:00
|
|
|
AddPendingEvent(evnt);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void ColorPickerScreenDropper::OnPaint(wxPaintEvent &)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-06-12 05:13:55 +02:00
|
|
|
wxPaintDC(this).DrawBitmap(capture, 0, 0);
|
|
|
|
}
|
2011-10-17 19:52:49 +02:00
|
|
|
|
2012-06-12 05:13:55 +02:00
|
|
|
void ColorPickerScreenDropper::DropFromScreenXY(int x, int y)
|
|
|
|
{
|
2010-08-03 04:16:26 +02:00
|
|
|
wxMemoryDC capdc(capture);
|
2012-06-12 05:13:55 +02:00
|
|
|
capdc.SetPen(*wxTRANSPARENT_PEN);
|
|
|
|
#ifndef __WXMAC__
|
|
|
|
wxScreenDC screen;
|
|
|
|
capdc.StretchBlit(0, 0, resx * magnification, resy * magnification,
|
|
|
|
&screen, x - resx / 2, y - resy / 2, resx, resy);
|
|
|
|
#else
|
|
|
|
// wxScreenDC doesn't work on recent versions of OS X so do it manually
|
|
|
|
|
|
|
|
// Doesn't bother handling the case where the rect overlaps two monitors
|
|
|
|
CGDirectDisplayID display_id;
|
|
|
|
uint32_t display_count;
|
|
|
|
CGGetDisplaysWithPoint(CGPointMake(x, y), 1, &display_id, &display_count);
|
|
|
|
|
|
|
|
agi::scoped_holder<CGImageRef> img(CGDisplayCreateImageForRect(display_id, CGRectMake(x - resx / 2, y - resy / 2, resx, resy)), CGImageRelease);
|
|
|
|
NSUInteger width = CGImageGetWidth(img);
|
|
|
|
NSUInteger height = CGImageGetHeight(img);
|
|
|
|
std::vector<uint8_t> imgdata(height * width * 4);
|
|
|
|
|
|
|
|
agi::scoped_holder<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB(), CGColorSpaceRelease);
|
|
|
|
agi::scoped_holder<CGContextRef> bmp_context(CGBitmapContextCreate(&imgdata[0], width, height, 8, 4 * width, colorspace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big), CGContextRelease);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-06-12 05:13:55 +02:00
|
|
|
CGContextDrawImage(bmp_context, CGRectMake(0, 0, width, height), img);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
for (int x = 0; x < resx; x++) {
|
|
|
|
for (int y = 0; y < resy; y++) {
|
2012-06-12 05:13:55 +02:00
|
|
|
uint8_t *pixel = &imgdata[y * width * 4 + x * 4];
|
|
|
|
capdc.SetBrush(wxBrush(wxColour(pixel[0], pixel[1], pixel[2])));
|
|
|
|
capdc.DrawRectangle(x * magnification, y * magnification, magnification, magnification);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
}
|
2010-08-03 04:16:26 +02:00
|
|
|
#endif
|
2007-07-05 00:16:24 +02:00
|
|
|
|
|
|
|
Refresh(false);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2012-09-25 01:35:27 +02:00
|
|
|
bool GetColorFromUser(wxWindow* parent, agi::Color original, std::function<void (agi::Color)> callback)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-10-09 04:07:54 +02:00
|
|
|
DialogColorPicker dialog(parent, original, callback);
|
2012-10-26 16:09:14 +02:00
|
|
|
bool ok = dialog.ShowModal() == wxID_OK;
|
|
|
|
if (!ok)
|
|
|
|
callback(original);
|
|
|
|
return ok;
|
2011-10-17 19:52:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static wxBitmap *make_rgb_image(int width, int offset) {
|
|
|
|
unsigned char *oslid = (unsigned char *)calloc(width * 256 * 3, 1);
|
|
|
|
unsigned char *slid = oslid + offset;
|
|
|
|
for (int y = 0; y < 256; y++) {
|
|
|
|
for (int x = 0; x < width; x++) {
|
|
|
|
*slid = clip_colorval(y);
|
|
|
|
slid += 3;
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
2011-10-17 19:52:49 +02:00
|
|
|
wxImage img(width, 256, oslid);
|
|
|
|
return new wxBitmap(img);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2012-09-25 01:35:27 +02:00
|
|
|
DialogColorPicker::DialogColorPicker(wxWindow *parent, agi::Color initial_color, std::function<void (agi::Color)> callback)
|
2012-04-03 19:38:50 +02:00
|
|
|
: wxDialog(parent, -1, _("Select Color"))
|
2010-06-09 10:14:50 +02:00
|
|
|
, callback(callback)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
memset(rgb_spectrum, 0, sizeof rgb_spectrum);
|
|
|
|
hsl_spectrum = 0;
|
|
|
|
hsv_spectrum = 0;
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
// generate spectrum slider bar images
|
2011-10-17 19:52:49 +02:00
|
|
|
rgb_slider[0] = make_rgb_image(slider_width, 0);
|
|
|
|
rgb_slider[1] = make_rgb_image(slider_width, 1);
|
|
|
|
rgb_slider[2] = make_rgb_image(slider_width, 2);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2006-03-22 17:07:49 +01:00
|
|
|
// luminance
|
2011-10-24 22:17:30 +02:00
|
|
|
unsigned char *slid = (unsigned char *)malloc(slider_width*256*3);
|
2006-01-16 22:02:54 +01:00
|
|
|
for (int y = 0; y < 256; y++) {
|
2011-10-24 22:17:30 +02:00
|
|
|
memset(slid + y * slider_width * 3, y, slider_width * 3);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
2011-10-24 22:17:30 +02:00
|
|
|
wxImage sliderimg(slider_width, 256, slid);
|
2006-03-22 17:07:49 +01:00
|
|
|
hsl_slider = new wxBitmap(sliderimg);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-24 22:17:30 +02:00
|
|
|
slid = (unsigned char *)malloc(slider_width*256*3);
|
2006-01-16 22:02:54 +01:00
|
|
|
for (int y = 0; y < 256; y++) {
|
2011-10-24 22:17:30 +02:00
|
|
|
unsigned char rgb[3];
|
|
|
|
hsv_to_rgb(y, 255, 255, rgb, rgb + 1, rgb + 2);
|
2006-01-16 22:02:54 +01:00
|
|
|
for (int x = 0; x < slider_width; x++) {
|
2011-10-24 22:17:30 +02:00
|
|
|
memcpy(slid + y * slider_width * 3 + x * 3, rgb, 3);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
}
|
2011-10-24 22:17:30 +02:00
|
|
|
sliderimg.SetData(slid);
|
2006-01-16 22:02:54 +01:00
|
|
|
hsv_slider = new wxBitmap(sliderimg);
|
|
|
|
|
|
|
|
// Create the controls for the dialog
|
2012-04-03 19:38:50 +02:00
|
|
|
wxSizer *spectrum_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Color spectrum"));
|
2011-10-17 19:52:49 +02:00
|
|
|
spectrum = new ColorPickerSpectrum(this, ColorPickerSpectrum::HorzVert, wxSize(256, 256));
|
|
|
|
slider = new ColorPickerSpectrum(this, ColorPickerSpectrum::Vert, wxSize(slider_width, 256));
|
|
|
|
wxString modes[] = { _("RGB/R"), _("RGB/G"), _("RGB/B"), _("HSL/L"), _("HSV/H") };
|
|
|
|
colorspace_choice = new wxChoice(this, -1, wxDefaultPosition, wxDefaultSize, 5, modes);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
wxSize colorinput_size(70, -1);
|
|
|
|
wxSize colorinput_labelsize(40, -1);
|
|
|
|
|
2012-04-03 19:38:50 +02:00
|
|
|
wxSizer *rgb_box = new wxStaticBoxSizer(wxHORIZONTAL, this, _("RGB color"));
|
|
|
|
wxSizer *hsl_box = new wxStaticBoxSizer(wxVERTICAL, this, _("HSL color"));
|
|
|
|
wxSizer *hsv_box = new wxStaticBoxSizer(wxVERTICAL, this, _("HSV color"));
|
2012-04-06 17:51:00 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < 3; ++i)
|
2011-10-17 19:52:49 +02:00
|
|
|
rgb_input[i] = new wxSpinCtrl(this, -1, "", wxDefaultPosition, colorinput_size, wxSP_ARROW_KEYS, 0, 255);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
ass_input = new wxTextCtrl(this, -1, "", wxDefaultPosition, colorinput_size);
|
|
|
|
html_input = new wxTextCtrl(this, -1, "", wxDefaultPosition, colorinput_size);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-04-06 17:51:00 +02:00
|
|
|
for (int i = 0; i < 3; ++i)
|
|
|
|
hsl_input[i] = new wxSpinCtrl(this, -1, "", wxDefaultPosition, colorinput_size, wxSP_ARROW_KEYS, 0, 255);
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; ++i)
|
|
|
|
hsv_input[i] = new wxSpinCtrl(this, -1, "", wxDefaultPosition, colorinput_size, wxSP_ARROW_KEYS, 0, 255);
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
preview_box = new wxStaticBitmap(this, -1, wxBitmap(40, 40, 24), wxDefaultPosition, wxSize(40, 40), STATIC_BORDER_FLAG);
|
|
|
|
recent_box = new ColorPickerRecent(this, 8, 4, 16);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2009-07-25 06:49:59 +02:00
|
|
|
eyedropper_bitmap = GETIMAGE(eyedropper_tool_24);
|
2007-07-05 00:16:24 +02:00
|
|
|
eyedropper_bitmap.SetMask(new wxMask(eyedropper_bitmap, wxColour(255, 0, 255)));
|
2011-10-17 19:52:49 +02:00
|
|
|
screen_dropper_icon = new wxStaticBitmap(this, -1, eyedropper_bitmap, wxDefaultPosition, wxDefaultSize, wxRAISED_BORDER);
|
|
|
|
screen_dropper = new ColorPickerScreenDropper(this, 7, 7, 8);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
// Arrange the controls in a nice way
|
|
|
|
wxSizer *spectop_sizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
spectop_sizer->Add(new wxStaticText(this, -1, _("Spectrum mode:")), 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxRIGHT, 5);
|
|
|
|
spectop_sizer->Add(colorspace_choice, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT);
|
|
|
|
spectop_sizer->Add(5, 5, 1, wxEXPAND);
|
|
|
|
spectop_sizer->Add(preview_box, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT);
|
2010-01-20 23:49:26 +01:00
|
|
|
wxSizer *spectrum_sizer = new wxFlexGridSizer(2, 5, 5);
|
2006-01-16 22:02:54 +01:00
|
|
|
spectrum_sizer->Add(spectop_sizer, wxEXPAND);
|
|
|
|
spectrum_sizer->AddStretchSpacer(1);
|
|
|
|
spectrum_sizer->Add(spectrum);
|
|
|
|
spectrum_sizer->Add(slider);
|
|
|
|
spectrum_box->Add(spectrum_sizer, 0, wxALL, 3);
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxString rgb_labels[] = { _("Red:"), _("Green:"), _("Blue:") };
|
|
|
|
rgb_box->Add(MakeColorInputSizer(rgb_labels, rgb_input), 1, wxALL|wxEXPAND, 3);
|
|
|
|
|
|
|
|
wxString ass_labels[] = { "ASS:", "HTML:" };
|
|
|
|
wxTextCtrl *ass_ctrls[] = { ass_input, html_input };
|
|
|
|
rgb_box->Add(MakeColorInputSizer(ass_labels, ass_ctrls), 0, wxALL|wxCENTER|wxEXPAND, 3);
|
|
|
|
|
|
|
|
wxString hsl_labels[] = { _("Hue:"), _("Sat.:"), _("Lum.:") };
|
|
|
|
hsl_box->Add(MakeColorInputSizer(hsl_labels, hsl_input), 0, wxALL|wxEXPAND, 3);
|
|
|
|
|
|
|
|
wxString hsv_labels[] = { _("Hue:"), _("Sat.:"), _("Value:") };
|
|
|
|
hsv_box->Add(MakeColorInputSizer(hsv_labels, hsv_input), 0, wxALL|wxEXPAND, 3);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2006-07-07 00:16:27 +02:00
|
|
|
wxSizer *hsx_sizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
hsx_sizer->Add(hsl_box);
|
|
|
|
hsx_sizer->AddSpacer(5);
|
|
|
|
hsx_sizer->Add(hsv_box);
|
|
|
|
|
2008-04-21 18:41:46 +02:00
|
|
|
wxSizer *recent_sizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
recent_sizer->Add(recent_box, 1, wxEXPAND);
|
|
|
|
|
2006-07-07 00:16:27 +02:00
|
|
|
wxSizer *picker_sizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
picker_sizer->AddStretchSpacer();
|
2007-07-05 00:16:24 +02:00
|
|
|
picker_sizer->Add(screen_dropper_icon, 0, wxALIGN_CENTER|wxRIGHT, 5);
|
2006-07-07 00:16:27 +02:00
|
|
|
picker_sizer->Add(screen_dropper, 0, wxALIGN_CENTER);
|
|
|
|
picker_sizer->AddStretchSpacer();
|
2008-04-21 18:41:46 +02:00
|
|
|
picker_sizer->Add(recent_sizer, 0, wxALIGN_CENTER);
|
2006-07-07 00:16:27 +02:00
|
|
|
picker_sizer->AddStretchSpacer();
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxStdDialogButtonSizer *button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxHELP);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2006-07-07 00:16:27 +02:00
|
|
|
wxSizer *input_sizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
input_sizer->Add(rgb_box, 0, wxALIGN_CENTER|wxEXPAND);
|
|
|
|
input_sizer->AddSpacer(5);
|
|
|
|
input_sizer->Add(hsx_sizer, 0, wxALIGN_CENTER|wxEXPAND);
|
|
|
|
input_sizer->AddStretchSpacer(1);
|
|
|
|
input_sizer->Add(picker_sizer, 0, wxALIGN_CENTER|wxEXPAND);
|
|
|
|
input_sizer->AddStretchSpacer(2);
|
|
|
|
input_sizer->Add(button_sizer, 0, wxALIGN_RIGHT|wxALIGN_BOTTOM);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
wxSizer *main_sizer = new wxBoxSizer(wxHORIZONTAL);
|
2008-01-18 18:07:00 +01:00
|
|
|
main_sizer->Add(spectrum_box, 1, wxALL | wxEXPAND, 5);
|
2006-07-07 00:16:27 +02:00
|
|
|
main_sizer->Add(input_sizer, 0, (wxALL&~wxLEFT)|wxEXPAND, 5);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
SetSizerAndFit(main_sizer);
|
|
|
|
|
|
|
|
persist.reset(new PersistLocation(this, "Tool/Colour Picker"));
|
|
|
|
|
2012-05-15 15:39:30 +02:00
|
|
|
// Fill the controls
|
|
|
|
int mode = OPT_GET("Tool/Colour Picker/Mode")->GetInt();
|
|
|
|
if (mode < 0 || mode > 4) mode = 3; // HSL default
|
|
|
|
colorspace_choice->SetSelection(mode);
|
|
|
|
SetColor(initial_color);
|
2012-10-26 16:09:14 +02:00
|
|
|
recent_box->Load(OPT_GET("Tool/Colour Picker/Recent Colours")->GetListColor());
|
2012-05-15 15:39:30 +02:00
|
|
|
|
2012-09-25 01:35:27 +02:00
|
|
|
using std::bind;
|
2011-10-17 19:52:49 +02:00
|
|
|
for (int i = 0; i < 3; ++i) {
|
|
|
|
rgb_input[i]->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, bind(&DialogColorPicker::UpdateFromRGB, this, true));
|
|
|
|
rgb_input[i]->Bind(wxEVT_COMMAND_TEXT_UPDATED, bind(&DialogColorPicker::UpdateFromRGB, this, true));
|
|
|
|
hsl_input[i]->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, bind(&DialogColorPicker::UpdateFromHSL, this, true));
|
|
|
|
hsl_input[i]->Bind(wxEVT_COMMAND_TEXT_UPDATED, bind(&DialogColorPicker::UpdateFromHSL, this, true));
|
|
|
|
hsv_input[i]->Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, bind(&DialogColorPicker::UpdateFromHSV, this, true));
|
|
|
|
hsv_input[i]->Bind(wxEVT_COMMAND_TEXT_UPDATED, bind(&DialogColorPicker::UpdateFromHSV, this, true));
|
|
|
|
}
|
2012-10-12 03:52:36 +02:00
|
|
|
ass_input->Bind(wxEVT_COMMAND_TEXT_UPDATED, bind(&DialogColorPicker::UpdateFromAss, this));
|
2011-10-17 19:52:49 +02:00
|
|
|
html_input->Bind(wxEVT_COMMAND_TEXT_UPDATED, bind(&DialogColorPicker::UpdateFromHTML, this));
|
|
|
|
|
|
|
|
screen_dropper_icon->Bind(wxEVT_MOTION, &DialogColorPicker::OnDropperMouse, this);
|
|
|
|
screen_dropper_icon->Bind(wxEVT_LEFT_DOWN, &DialogColorPicker::OnDropperMouse, this);
|
|
|
|
screen_dropper_icon->Bind(wxEVT_LEFT_UP, &DialogColorPicker::OnDropperMouse, this);
|
2011-12-22 22:26:30 +01:00
|
|
|
screen_dropper_icon->Bind(wxEVT_MOUSE_CAPTURE_LOST, &DialogColorPicker::OnCaptureLost, this);
|
2011-10-17 19:52:49 +02:00
|
|
|
Bind(wxEVT_MOTION, &DialogColorPicker::OnMouse, this);
|
|
|
|
Bind(wxEVT_LEFT_DOWN, &DialogColorPicker::OnMouse, this);
|
|
|
|
Bind(wxEVT_LEFT_UP, &DialogColorPicker::OnMouse, this);
|
|
|
|
|
|
|
|
spectrum->Bind(EVT_SPECTRUM_CHANGE, &DialogColorPicker::OnSpectrumChange, this);
|
|
|
|
slider->Bind(EVT_SPECTRUM_CHANGE, &DialogColorPicker::OnSliderChange, this);
|
|
|
|
recent_box->Bind(EVT_RECENT_SELECT, &DialogColorPicker::OnRecentSelect, this);
|
|
|
|
screen_dropper->Bind(EVT_DROPPER_SELECT, &DialogColorPicker::OnRecentSelect, this);
|
|
|
|
|
|
|
|
colorspace_choice->Bind(wxEVT_COMMAND_CHOICE_SELECTED, &DialogColorPicker::OnChangeMode, this);
|
|
|
|
|
2012-01-08 02:05:07 +01:00
|
|
|
button_sizer->GetHelpButton()->Bind(wxEVT_COMMAND_BUTTON_CLICKED, bind(&HelpButton::OpenPage, "Colour Picker"));
|
2011-10-17 19:52:49 +02:00
|
|
|
}
|
2007-07-05 00:16:24 +02:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
template<int N, class Control>
|
|
|
|
wxSizer *DialogColorPicker::MakeColorInputSizer(wxString (&labels)[N], Control *(&inputs)[N])
|
|
|
|
{
|
|
|
|
wxFlexGridSizer * sizer = new wxFlexGridSizer(2, 5, 5);
|
|
|
|
for (int i = 0; i < N; ++i) {
|
2012-05-15 15:39:40 +02:00
|
|
|
sizer->Add(new wxStaticText(this, -1, labels[i]), wxSizerFlags(1).Center().Left());
|
2011-10-17 19:52:49 +02:00
|
|
|
sizer->Add(inputs[i]);
|
|
|
|
}
|
|
|
|
sizer->AddGrowableCol(0,1);
|
|
|
|
return sizer;
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
DialogColorPicker::~DialogColorPicker()
|
|
|
|
{
|
|
|
|
delete rgb_spectrum[0];
|
|
|
|
delete rgb_spectrum[1];
|
|
|
|
delete rgb_spectrum[2];
|
|
|
|
delete hsl_spectrum;
|
|
|
|
delete hsv_spectrum;
|
|
|
|
delete rgb_slider[0];
|
|
|
|
delete rgb_slider[1];
|
|
|
|
delete rgb_slider[2];
|
2006-03-16 02:26:26 +01:00
|
|
|
delete hsl_slider;
|
2006-01-16 22:02:54 +01:00
|
|
|
delete hsv_slider;
|
2009-11-01 08:28:09 +01:00
|
|
|
|
|
|
|
if (screen_dropper_icon->HasCapture()) screen_dropper_icon->ReleaseMouse();
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
/// @brief Sets the currently selected color, and updates all controls
|
2012-10-26 16:09:14 +02:00
|
|
|
void DialogColorPicker::SetColor(agi::Color new_color)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-10-26 16:09:14 +02:00
|
|
|
SetRGB(new_color);
|
2010-10-16 22:11:48 +02:00
|
|
|
spectrum_dirty = true;
|
2006-01-16 22:02:54 +01:00
|
|
|
UpdateFromRGB();
|
|
|
|
}
|
|
|
|
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
/// @brief Get the currently selected color
|
2012-10-26 16:09:14 +02:00
|
|
|
agi::Color DialogColorPicker::GetColor()
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
|
|
|
recent_box->AddColor(cur_color);
|
2012-10-26 16:09:14 +02:00
|
|
|
OPT_SET("Tool/Colour Picker/Recent Colours")->SetListColor(recent_box->Save());
|
2006-01-16 22:02:54 +01:00
|
|
|
return cur_color;
|
|
|
|
}
|
|
|
|
|
2012-05-15 15:39:35 +02:00
|
|
|
static void change_value(wxSpinCtrl *ctrl, int value)
|
|
|
|
{
|
|
|
|
wxEventBlocker blocker(ctrl);
|
|
|
|
ctrl->SetValue(value);
|
|
|
|
}
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
void DialogColorPicker::SetRGB(agi::Color new_color)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-10-26 16:09:14 +02:00
|
|
|
change_value(rgb_input[0], new_color.r);
|
|
|
|
change_value(rgb_input[1], new_color.g);
|
|
|
|
change_value(rgb_input[2], new_color.b);
|
|
|
|
cur_color = new_color;
|
2011-10-17 19:52:49 +02:00
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
void DialogColorPicker::SetHSL(unsigned char r, unsigned char g, unsigned char b)
|
|
|
|
{
|
|
|
|
unsigned char h, s, l;
|
2006-01-16 22:02:54 +01:00
|
|
|
rgb_to_hsl(r, g, b, &h, &s, &l);
|
2012-05-15 15:39:35 +02:00
|
|
|
change_value(hsl_input[0], h);
|
|
|
|
change_value(hsl_input[1], s);
|
|
|
|
change_value(hsl_input[2], l);
|
2011-10-17 19:52:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void DialogColorPicker::SetHSV(unsigned char r, unsigned char g, unsigned char b)
|
|
|
|
{
|
|
|
|
unsigned char h, s, v;
|
|
|
|
rgb_to_hsv(r, g, b, &h, &s, &v);
|
2012-05-15 15:39:35 +02:00
|
|
|
change_value(hsv_input[0], h);
|
|
|
|
change_value(hsv_input[1], s);
|
|
|
|
change_value(hsv_input[2], v);
|
2011-10-17 19:52:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// @brief Use the values entered in the RGB controls to update the other controls
|
|
|
|
void DialogColorPicker::UpdateFromRGB(bool dirty)
|
|
|
|
{
|
|
|
|
unsigned char r, g, b;
|
|
|
|
r = rgb_input[0]->GetValue();
|
|
|
|
g = rgb_input[1]->GetValue();
|
|
|
|
b = rgb_input[2]->GetValue();
|
|
|
|
SetHSL(r, g, b);
|
|
|
|
SetHSV(r, g, b);
|
2012-10-26 16:09:14 +02:00
|
|
|
cur_color = agi::Color(r, g, b);
|
2012-11-22 17:21:47 +01:00
|
|
|
ass_input->ChangeValue(to_wx(cur_color.GetAssOverrideFormatted()));
|
2012-10-26 16:09:14 +02:00
|
|
|
html_input->ChangeValue(to_wx(cur_color.GetHexFormatted()));
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
if (dirty)
|
|
|
|
spectrum_dirty = true;
|
|
|
|
UpdateSpectrumDisplay();
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
/// @brief Use the values entered in the HSL controls to update the other controls
|
2011-10-17 19:52:49 +02:00
|
|
|
void DialogColorPicker::UpdateFromHSL(bool dirty)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
unsigned char r, g, b, h, s, l;
|
2006-01-16 22:02:54 +01:00
|
|
|
h = hsl_input[0]->GetValue();
|
|
|
|
s = hsl_input[1]->GetValue();
|
|
|
|
l = hsl_input[2]->GetValue();
|
|
|
|
hsl_to_rgb(h, s, l, &r, &g, &b);
|
2012-10-26 16:09:14 +02:00
|
|
|
SetRGB(agi::Color(r, g, b));
|
2011-10-17 19:52:49 +02:00
|
|
|
SetHSV(r, g, b);
|
|
|
|
|
2012-11-22 17:21:47 +01:00
|
|
|
ass_input->ChangeValue(to_wx(cur_color.GetAssOverrideFormatted()));
|
2012-10-26 16:09:14 +02:00
|
|
|
html_input->ChangeValue(to_wx(cur_color.GetHexFormatted()));
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
if (dirty)
|
|
|
|
spectrum_dirty = true;
|
|
|
|
UpdateSpectrumDisplay();
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// @brief Use the values entered in the HSV controls to update the other controls
|
|
|
|
void DialogColorPicker::UpdateFromHSV(bool dirty)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
unsigned char r, g, b, h, s, v;
|
|
|
|
h = hsv_input[0]->GetValue();
|
|
|
|
s = hsv_input[1]->GetValue();
|
|
|
|
v = hsv_input[2]->GetValue();
|
|
|
|
hsv_to_rgb(h, s, v, &r, &g, &b);
|
2012-10-26 16:09:14 +02:00
|
|
|
SetRGB(agi::Color(r, g, b));
|
2011-10-17 19:52:49 +02:00
|
|
|
SetHSL(r, g, b);
|
2012-11-22 17:21:47 +01:00
|
|
|
ass_input->ChangeValue(to_wx(cur_color.GetAssOverrideFormatted()));
|
2012-10-26 16:09:14 +02:00
|
|
|
html_input->ChangeValue(to_wx(cur_color.GetHexFormatted()));
|
2011-10-17 19:52:49 +02:00
|
|
|
|
|
|
|
if (dirty)
|
|
|
|
spectrum_dirty = true;
|
2006-01-16 22:02:54 +01:00
|
|
|
UpdateSpectrumDisplay();
|
|
|
|
}
|
|
|
|
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
/// @brief Use the value entered in the ASS hex control to update the other controls
|
2012-10-12 03:52:36 +02:00
|
|
|
void DialogColorPicker::UpdateFromAss()
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-10-26 16:09:14 +02:00
|
|
|
agi::Color color(from_wx(ass_input->GetValue()));
|
|
|
|
SetRGB(color);
|
|
|
|
SetHSL(color.r, color.g, color.b);
|
|
|
|
SetHSV(color.r, color.g, color.b);
|
|
|
|
html_input->ChangeValue(to_wx(cur_color.GetHexFormatted()));
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
spectrum_dirty = true;
|
|
|
|
UpdateSpectrumDisplay();
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
/// @brief Use the value entered in the HTML hex control to update the other controls
|
2006-01-16 22:02:54 +01:00
|
|
|
void DialogColorPicker::UpdateFromHTML()
|
|
|
|
{
|
2012-10-26 16:09:14 +02:00
|
|
|
agi::Color color(from_wx(html_input->GetValue()));
|
|
|
|
SetRGB(color);
|
|
|
|
SetHSL(color.r, color.g, color.b);
|
|
|
|
SetHSV(color.r, color.g, color.b);
|
2012-11-22 17:29:33 +01:00
|
|
|
ass_input->ChangeValue(to_wx(cur_color.GetAssOverrideFormatted()));
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
spectrum_dirty = true;
|
|
|
|
UpdateSpectrumDisplay();
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DialogColorPicker::UpdateSpectrumDisplay()
|
|
|
|
{
|
|
|
|
int i = colorspace_choice->GetSelection();
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
|
|
|
if (spectrum_dirty)
|
2010-06-18 09:14:11 +02:00
|
|
|
spectrum->SetBackground(MakeGBSpectrum(), true);
|
2006-01-16 22:02:54 +01:00
|
|
|
slider->SetBackground(rgb_slider[0]);
|
|
|
|
slider->SetXY(0, rgb_input[0]->GetValue());
|
|
|
|
spectrum->SetXY(rgb_input[2]->GetValue(), rgb_input[1]->GetValue());
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (spectrum_dirty)
|
2010-06-18 09:14:11 +02:00
|
|
|
spectrum->SetBackground(MakeRBSpectrum(), true);
|
2006-01-16 22:02:54 +01:00
|
|
|
slider->SetBackground(rgb_slider[1]);
|
|
|
|
slider->SetXY(0, rgb_input[1]->GetValue());
|
|
|
|
spectrum->SetXY(rgb_input[2]->GetValue(), rgb_input[0]->GetValue());
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (spectrum_dirty)
|
2010-06-18 09:14:11 +02:00
|
|
|
spectrum->SetBackground(MakeRGSpectrum(), true);
|
2006-01-16 22:02:54 +01:00
|
|
|
slider->SetBackground(rgb_slider[2]);
|
|
|
|
slider->SetXY(0, rgb_input[2]->GetValue());
|
|
|
|
spectrum->SetXY(rgb_input[1]->GetValue(), rgb_input[0]->GetValue());
|
|
|
|
break;
|
2006-03-16 02:26:26 +01:00
|
|
|
case 3:
|
2006-01-16 22:02:54 +01:00
|
|
|
if (spectrum_dirty)
|
2010-06-18 09:14:11 +02:00
|
|
|
spectrum->SetBackground(MakeHSSpectrum(), true);
|
2006-01-16 22:02:54 +01:00
|
|
|
slider->SetBackground(hsl_slider);
|
|
|
|
slider->SetXY(0, hsl_input[2]->GetValue());
|
|
|
|
spectrum->SetXY(hsl_input[1]->GetValue(), hsl_input[0]->GetValue());
|
|
|
|
break;
|
2006-03-16 02:26:26 +01:00
|
|
|
case 4:
|
2006-01-16 22:02:54 +01:00
|
|
|
if (spectrum_dirty)
|
2010-06-18 09:14:11 +02:00
|
|
|
spectrum->SetBackground(MakeSVSpectrum(), true);
|
2006-01-16 22:02:54 +01:00
|
|
|
slider->SetBackground(hsv_slider);
|
|
|
|
slider->SetXY(0, hsv_input[0]->GetValue());
|
|
|
|
spectrum->SetXY(hsv_input[1]->GetValue(), hsv_input[2]->GetValue());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
spectrum_dirty = false;
|
|
|
|
|
2007-01-01 23:56:16 +01:00
|
|
|
wxBitmap tempBmp = preview_box->GetBitmap();
|
|
|
|
{
|
|
|
|
wxMemoryDC previewdc;
|
|
|
|
previewdc.SelectObject(tempBmp);
|
|
|
|
previewdc.SetPen(*wxTRANSPARENT_PEN);
|
2012-10-26 16:09:14 +02:00
|
|
|
previewdc.SetBrush(wxBrush(to_wx(cur_color)));
|
2007-01-01 23:56:16 +01:00
|
|
|
previewdc.DrawRectangle(0, 0, 40, 40);
|
|
|
|
}
|
|
|
|
preview_box->SetBitmap(tempBmp);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-10-09 04:07:54 +02:00
|
|
|
callback(cur_color);
|
2010-06-09 10:14:50 +02:00
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
wxBitmap *DialogColorPicker::MakeGBSpectrum()
|
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
delete rgb_spectrum[0];
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
wxImage spectrum_image(256, 256, false);
|
|
|
|
unsigned char *ospec, *spec;
|
|
|
|
|
|
|
|
ospec = spec = (unsigned char *)malloc(256*256*3);
|
2011-12-26 23:20:49 +01:00
|
|
|
if (!spec) throw std::bad_alloc();
|
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
for (int g = 0; g < 256; g++) {
|
|
|
|
for (int b = 0; b < 256; b++) {
|
2012-10-26 16:09:14 +02:00
|
|
|
*spec++ = cur_color.r;
|
2006-01-16 22:02:54 +01:00
|
|
|
*spec++ = g;
|
|
|
|
*spec++ = b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
spectrum_image.SetData(ospec);
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
return rgb_spectrum[0] = new wxBitmap(spectrum_image);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
wxBitmap *DialogColorPicker::MakeRBSpectrum()
|
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
delete rgb_spectrum[1];
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
unsigned char *ospec, *spec;
|
|
|
|
ospec = spec = (unsigned char *)malloc(256*256*3);
|
2011-12-26 23:20:49 +01:00
|
|
|
if (!spec) throw std::bad_alloc();
|
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
for (int r = 0; r < 256; r++) {
|
|
|
|
for (int b = 0; b < 256; b++) {
|
|
|
|
*spec++ = r;
|
2012-10-26 16:09:14 +02:00
|
|
|
*spec++ = cur_color.g;
|
2006-01-16 22:02:54 +01:00
|
|
|
*spec++ = b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxImage spectrum_image(256, 256, ospec);
|
|
|
|
return rgb_spectrum[1] = new wxBitmap(spectrum_image);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
wxBitmap *DialogColorPicker::MakeRGSpectrum()
|
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
delete rgb_spectrum[2];
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
unsigned char *ospec, *spec;
|
|
|
|
ospec = spec = (unsigned char *)malloc(256*256*3);
|
2011-12-26 23:20:49 +01:00
|
|
|
if (!spec) throw std::bad_alloc();
|
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
for (int r = 0; r < 256; r++) {
|
|
|
|
for (int g = 0; g < 256; g++) {
|
|
|
|
*spec++ = r;
|
|
|
|
*spec++ = g;
|
2012-10-26 16:09:14 +02:00
|
|
|
*spec++ = cur_color.b;
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxImage spectrum_image(256, 256, ospec);
|
|
|
|
return rgb_spectrum[2] = new wxBitmap(spectrum_image);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
wxBitmap *DialogColorPicker::MakeHSSpectrum()
|
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
delete hsl_spectrum;
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
unsigned char *ospec, *spec;
|
|
|
|
ospec = spec = (unsigned char *)malloc(256*256*3);
|
2011-12-26 23:20:49 +01:00
|
|
|
if (!spec) throw std::bad_alloc();
|
|
|
|
|
2006-01-16 22:02:54 +01:00
|
|
|
int l = hsl_input[2]->GetValue();
|
|
|
|
|
|
|
|
for (int h = 0; h < 256; h++) {
|
|
|
|
unsigned char maxr, maxg, maxb;
|
|
|
|
hsl_to_rgb(h, 255, l, &maxr, &maxg, &maxb);
|
|
|
|
|
|
|
|
for (int s = 0; s < 256; s++) {
|
|
|
|
*spec++ = maxr * s / 256 + (255-s) * l / 256;
|
|
|
|
*spec++ = maxg * s / 256 + (255-s) * l / 256;
|
|
|
|
*spec++ = maxb * s / 256 + (255-s) * l / 256;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxImage spectrum_image(256, 256, ospec);
|
|
|
|
return hsl_spectrum = new wxBitmap(spectrum_image);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
wxBitmap *DialogColorPicker::MakeSVSpectrum()
|
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
delete hsv_spectrum;
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
unsigned char *ospec, *spec;
|
|
|
|
ospec = spec = (unsigned char *)malloc(256*256*3);
|
2011-12-26 23:20:49 +01:00
|
|
|
if (!spec) throw std::bad_alloc();
|
2006-01-16 22:02:54 +01:00
|
|
|
|
|
|
|
int h = hsv_input[0]->GetValue();
|
|
|
|
unsigned char maxr, maxg, maxb;
|
|
|
|
hsv_to_rgb(h, 255, 255, &maxr, &maxg, &maxb);
|
|
|
|
|
|
|
|
for (int v = 0; v < 256; v++) {
|
2011-10-17 19:52:49 +02:00
|
|
|
int rr = (255-maxr) * v / 256;
|
|
|
|
int rg = (255-maxg) * v / 256;
|
|
|
|
int rb = (255-maxb) * v / 256;
|
2006-01-16 22:02:54 +01:00
|
|
|
for (int s = 0; s < 256; s++) {
|
2011-10-17 19:52:49 +02:00
|
|
|
*spec++ = 255 - rr * s / 256 - (255-v);
|
|
|
|
*spec++ = 255 - rg * s / 256 - (255-v);
|
|
|
|
*spec++ = 255 - rb * s / 256 - (255-v);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
wxImage spectrum_image(256, 256, ospec);
|
|
|
|
return hsv_spectrum = new wxBitmap(spectrum_image);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogColorPicker::OnChangeMode(wxCommandEvent &)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2011-10-17 19:52:49 +02:00
|
|
|
spectrum_dirty = true;
|
2010-05-21 03:13:36 +02:00
|
|
|
OPT_SET("Tool/Colour Picker/Mode")->SetInt(colorspace_choice->GetSelection());
|
2006-01-16 22:02:54 +01:00
|
|
|
UpdateSpectrumDisplay();
|
|
|
|
}
|
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogColorPicker::OnSpectrumChange(wxCommandEvent &)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
|
|
|
int i = colorspace_choice->GetSelection();
|
|
|
|
switch (i) {
|
|
|
|
case 0:
|
2012-05-15 15:39:45 +02:00
|
|
|
change_value(rgb_input[2], spectrum->GetX());
|
|
|
|
change_value(rgb_input[1], spectrum->GetY());
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
|
|
|
case 1:
|
2012-05-15 15:39:45 +02:00
|
|
|
change_value(rgb_input[2], spectrum->GetX());
|
|
|
|
change_value(rgb_input[0], spectrum->GetY());
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
|
|
|
case 2:
|
2012-05-15 15:39:45 +02:00
|
|
|
change_value(rgb_input[1], spectrum->GetX());
|
|
|
|
change_value(rgb_input[0], spectrum->GetY());
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
2006-03-16 02:26:26 +01:00
|
|
|
case 3:
|
2012-05-15 15:39:45 +02:00
|
|
|
change_value(hsl_input[1], spectrum->GetX());
|
|
|
|
change_value(hsl_input[0], spectrum->GetY());
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
2006-03-16 02:26:26 +01:00
|
|
|
case 4:
|
2012-05-15 15:39:45 +02:00
|
|
|
change_value(hsv_input[1], spectrum->GetX());
|
|
|
|
change_value(hsv_input[2], spectrum->GetY());
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
switch (i) {
|
|
|
|
case 0: case 1: case 2:
|
|
|
|
UpdateFromRGB(false);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
UpdateFromHSL(false);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
UpdateFromHSV(false);
|
|
|
|
break;
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2011-10-17 19:52:49 +02:00
|
|
|
void DialogColorPicker::OnSliderChange(wxCommandEvent &)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
|
|
|
spectrum_dirty = true;
|
|
|
|
int i = colorspace_choice->GetSelection();
|
|
|
|
switch (i) {
|
2011-10-17 19:52:49 +02:00
|
|
|
case 0: case 1: case 2:
|
2012-05-15 15:39:45 +02:00
|
|
|
change_value(rgb_input[i], slider->GetY());
|
2011-10-17 19:52:49 +02:00
|
|
|
UpdateFromRGB(false);
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
2006-03-16 02:26:26 +01:00
|
|
|
case 3:
|
2012-05-15 15:39:45 +02:00
|
|
|
change_value(hsl_input[2], slider->GetY());
|
2011-10-17 19:52:49 +02:00
|
|
|
UpdateFromHSL(false);
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
2006-03-16 02:26:26 +01:00
|
|
|
case 4:
|
2012-05-15 15:39:45 +02:00
|
|
|
change_value(hsv_input[0], slider->GetY());
|
2011-10-17 19:52:49 +02:00
|
|
|
UpdateFromHSV(false);
|
2006-01-16 22:02:54 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-26 16:09:14 +02:00
|
|
|
void DialogColorPicker::OnRecentSelect(wxThreadEvent &evt)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-10-26 16:09:14 +02:00
|
|
|
SetColor(evt.GetPayload<agi::Color>());
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2007-07-05 00:16:24 +02:00
|
|
|
void DialogColorPicker::OnDropperMouse(wxMouseEvent &evt)
|
|
|
|
{
|
2007-07-05 01:47:20 +02:00
|
|
|
if (evt.LeftDown() && !screen_dropper_icon->HasCapture()) {
|
2007-07-05 00:16:24 +02:00
|
|
|
#ifdef WIN32
|
2011-09-28 21:43:11 +02:00
|
|
|
screen_dropper_icon->SetCursor(wxCursor("eyedropper_cursor"));
|
2007-07-05 00:16:24 +02:00
|
|
|
#else
|
2007-07-05 01:47:20 +02:00
|
|
|
screen_dropper_icon->SetCursor(*wxCROSS_CURSOR);
|
2007-07-05 00:16:24 +02:00
|
|
|
#endif
|
2007-07-05 01:47:20 +02:00
|
|
|
screen_dropper_icon->SetBitmap(wxNullBitmap);
|
2010-01-12 04:19:49 +01:00
|
|
|
screen_dropper_icon->CaptureMouse();
|
|
|
|
eyedropper_grab_point = evt.GetPosition();
|
|
|
|
eyedropper_is_grabbed = false;
|
2007-07-05 00:16:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (evt.LeftUp()) {
|
|
|
|
wxPoint ptdiff = evt.GetPosition() - eyedropper_grab_point;
|
2011-10-17 19:52:49 +02:00
|
|
|
bool release_now = eyedropper_is_grabbed || abs(ptdiff.x) + abs(ptdiff.y) > 7;
|
2007-07-05 01:47:20 +02:00
|
|
|
if (release_now) {
|
|
|
|
screen_dropper_icon->ReleaseMouse();
|
|
|
|
eyedropper_is_grabbed = false;
|
|
|
|
screen_dropper_icon->SetCursor(wxNullCursor);
|
|
|
|
screen_dropper_icon->SetBitmap(eyedropper_bitmap);
|
|
|
|
} else {
|
|
|
|
eyedropper_is_grabbed = true;
|
|
|
|
}
|
2007-07-05 00:16:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (screen_dropper_icon->HasCapture()) {
|
|
|
|
wxPoint scrpos = screen_dropper_icon->ClientToScreen(evt.GetPosition());
|
|
|
|
screen_dropper->DropFromScreenXY(scrpos.x, scrpos.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-12 04:19:49 +01:00
|
|
|
/// @brief Hack to redirect events to the screen dropper icon
|
|
|
|
void DialogColorPicker::OnMouse(wxMouseEvent &evt)
|
|
|
|
{
|
|
|
|
if (screen_dropper_icon->HasCapture()) {
|
|
|
|
wxPoint dropper_pos = screen_dropper_icon->ScreenToClient(ClientToScreen(evt.GetPosition()));
|
|
|
|
evt.m_x = dropper_pos.x;
|
|
|
|
evt.m_y = dropper_pos.y;
|
|
|
|
screen_dropper_icon->GetEventHandler()->ProcessEvent(evt);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
evt.Skip();
|
|
|
|
}
|
2011-12-22 22:26:30 +01:00
|
|
|
|
|
|
|
void DialogColorPicker::OnCaptureLost(wxMouseCaptureLostEvent&) {
|
|
|
|
eyedropper_is_grabbed = false;
|
|
|
|
screen_dropper_icon->SetCursor(wxNullCursor);
|
|
|
|
screen_dropper_icon->SetBitmap(eyedropper_bitmap);
|
|
|
|
}
|