summaryrefslogtreecommitdiff
path: root/src/CustomComponents.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/CustomComponents.vala')
-rw-r--r--src/CustomComponents.vala513
1 files changed, 0 insertions, 513 deletions
diff --git a/src/CustomComponents.vala b/src/CustomComponents.vala
deleted file mode 100644
index 0a08c93..0000000
--- a/src/CustomComponents.vala
+++ /dev/null
@@ -1,513 +0,0 @@
-/* Copyright 2016 Software Freedom Conservancy Inc.
- *
- * This software is licensed under the GNU LGPL (version 2.1 or later).
- * See the COPYING file in this distribution.
- */
-
-extern void qsort(void *p, size_t num, size_t size, GLib.CompareFunc func);
-
-public class ThemeLoader {
- private struct LightweightColor {
- public uchar red;
- public uchar green;
- public uchar blue;
-
- public LightweightColor() {
- red = green = blue = 0;
- }
- }
-
- private const int NUM_SUPPORTED_INTENSITIES = 6;
- private const int THEME_OUTLINE_COLOR = 0;
- private const int THEME_BEVEL_DARKER_COLOR = 1;
- private const int THEME_BEVEL_DARK_COLOR = 2;
- private const int THEME_BASE_COLOR = 3;
- private const int THEME_BEVEL_LIGHT_COLOR = 4;
- private const int THEME_BEVEL_LIGHTER_COLOR = 5;
-
- private static LightweightColor[] theme_colors = null;
-
- private static void populate_theme_params() {
- if (theme_colors != null)
- return;
-
- theme_colors = new LightweightColor[NUM_SUPPORTED_INTENSITIES];
-
- Gtk.Settings settings = Gtk.Settings.get_default();
- HashTable<string, Gdk.Color?> color_table = settings.color_hash;
- Gdk.Color? base_color = color_table.lookup("bg_color");
- if (base_color == null && !Gdk.Color.parse("#fff", out base_color))
- error("can't parse color");
-
- RGBAnalyticPixel base_color_analytic_rgb =
- RGBAnalyticPixel.from_quantized_components(base_color.red >> 8,
- base_color.green >> 8, base_color.blue >> 8);
- HSVAnalyticPixel base_color_analytic_hsv =
- HSVAnalyticPixel.from_rgb(base_color_analytic_rgb);
-
- HSVAnalyticPixel bevel_light_analytic_hsv = base_color_analytic_hsv;
- bevel_light_analytic_hsv.light_value *= 1.15f;
- bevel_light_analytic_hsv.light_value =
- bevel_light_analytic_hsv.light_value.clamp(0.0f, 1.0f);
-
- HSVAnalyticPixel bevel_lighter_analytic_hsv = bevel_light_analytic_hsv;
- bevel_lighter_analytic_hsv.light_value *= 1.15f;
- bevel_lighter_analytic_hsv.light_value =
- bevel_lighter_analytic_hsv.light_value.clamp(0.0f, 1.0f);
-
- HSVAnalyticPixel bevel_dark_analytic_hsv = base_color_analytic_hsv;
- bevel_dark_analytic_hsv.light_value *= 0.85f;
- bevel_dark_analytic_hsv.light_value =
- bevel_dark_analytic_hsv.light_value.clamp(0.0f, 1.0f);
-
- HSVAnalyticPixel bevel_darker_analytic_hsv = bevel_dark_analytic_hsv;
- bevel_darker_analytic_hsv.light_value *= 0.85f;
- bevel_darker_analytic_hsv.light_value =
- bevel_darker_analytic_hsv.light_value.clamp(0.0f, 1.0f);
-
- HSVAnalyticPixel outline_analytic_hsv = bevel_darker_analytic_hsv;
- outline_analytic_hsv.light_value *= 0.66f;
- outline_analytic_hsv.light_value =
- outline_analytic_hsv.light_value.clamp(0.0f, 1.0f);
-
- RGBAnalyticPixel outline_analytic_rgb = outline_analytic_hsv.to_rgb();
- theme_colors[THEME_OUTLINE_COLOR] =
- populate_one_theme_param(outline_analytic_rgb);
-
- RGBAnalyticPixel bevel_darker_analytic_rgb = bevel_darker_analytic_hsv.to_rgb();
- theme_colors[THEME_BEVEL_DARKER_COLOR] =
- populate_one_theme_param(bevel_darker_analytic_rgb);
-
- RGBAnalyticPixel bevel_dark_analytic_rgb = bevel_dark_analytic_hsv.to_rgb();
- theme_colors[THEME_BEVEL_DARK_COLOR] =
- populate_one_theme_param(bevel_dark_analytic_rgb);
-
- theme_colors[THEME_BASE_COLOR] =
- populate_one_theme_param(base_color_analytic_rgb);
-
- RGBAnalyticPixel bevel_light_analytic_rgb = bevel_light_analytic_hsv.to_rgb();
- theme_colors[THEME_BEVEL_LIGHT_COLOR] =
- populate_one_theme_param(bevel_light_analytic_rgb);
-
- RGBAnalyticPixel bevel_lighter_analytic_rgb = bevel_light_analytic_hsv.to_rgb();
- theme_colors[THEME_BEVEL_LIGHTER_COLOR] =
- populate_one_theme_param(bevel_lighter_analytic_rgb);
- }
-
- private static LightweightColor populate_one_theme_param(RGBAnalyticPixel from) {
- LightweightColor into = LightweightColor();
-
- into.red = (uchar)(from.red * 255.0f);
- into.green = (uchar)(from.green * 255.0f);
- into.blue = (uchar)(from.blue * 255.0f);
-
- return into;
- }
-
- public static Gdk.Pixbuf load_icon(string source_basename) {
- populate_theme_params();
-
- Gdk.Pixbuf loaded_pixbuf = Resources.get_icon(source_basename, 0).copy();
-
- /* Sweep through the icon image data loaded from disk and determine how many
- unique colors are in it. We do this with the aid of a HashSet. */
- Gee.HashSet<RGBAnalyticPixel?> colors =
- new Gee.HashSet<RGBAnalyticPixel?>(rgb_pixel_hash_func,
- rgb_pixel_equal_func);
- unowned uchar[] pixel_data = loaded_pixbuf.get_pixels();
- for (int j = 0; j < loaded_pixbuf.height; j++) {
- for (int i = 0; i < loaded_pixbuf.width; i++) {
- int pixel_index = (j * loaded_pixbuf.rowstride) + (i * loaded_pixbuf.n_channels);
-
- RGBAnalyticPixel pixel_color = RGBAnalyticPixel.from_quantized_components(
- pixel_data[pixel_index], pixel_data[pixel_index + 1],
- pixel_data[pixel_index + 2]);
- colors.add(pixel_color);
- }
- }
-
- /* If the image data loaded from disk didn't contain NUM_SUPPORTED_INTENSITIES
- colors, then we can't unambiguously map the colors in the loaded image data
- to theme colors on the user's system, so propagate an error */
- if (colors.size != NUM_SUPPORTED_INTENSITIES)
- error("ThemeLoader: load_icon: pixbuf does not contain the correct number " +
- "of unique colors");
-
- /* sort the colors in the loaded image data in order of increasing intensity; this
- means that we have to convert the loaded colors from RGB to HSV format */
- HSVAnalyticPixel[] hsv_pixels = new HSVAnalyticPixel[6];
- int pixel_ticker = 0;
- foreach (RGBAnalyticPixel rgb_pixel in colors)
- hsv_pixels[pixel_ticker++] = HSVAnalyticPixel.from_rgb(rgb_pixel);
- qsort(hsv_pixels, hsv_pixels.length, sizeof(HSVAnalyticPixel), hsv_pixel_compare_func);
-
- /* step through each pixel in the image data loaded from disk and map its color
- to one of the user's theme colors */
- for (int j = 0; j < loaded_pixbuf.height; j++) {
- for (int i = 0; i < loaded_pixbuf.width; i++) {
- int pixel_index = (j * loaded_pixbuf.rowstride) + (i * loaded_pixbuf.n_channels);
- RGBAnalyticPixel pixel_color = RGBAnalyticPixel.from_quantized_components(
- pixel_data[pixel_index], pixel_data[pixel_index + 1],
- pixel_data[pixel_index + 2]);
- HSVAnalyticPixel pixel_color_hsv = HSVAnalyticPixel.from_rgb(pixel_color);
- int this_intensity = 0;
- for (int k = 0; k < NUM_SUPPORTED_INTENSITIES; k++) {
- if (hsv_pixels[k].light_value == pixel_color_hsv.light_value) {
- this_intensity = k;
- break;
- }
- }
- pixel_data[pixel_index] = theme_colors[this_intensity].red;
- pixel_data[pixel_index + 1] = theme_colors[this_intensity].green;
- pixel_data[pixel_index + 2] = theme_colors[this_intensity].blue;
- }
- }
-
- return loaded_pixbuf;
- }
-
- private static int hsv_pixel_compare_func(void* pixval1, void* pixval2) {
- HSVAnalyticPixel pixel_val_1 = * ((HSVAnalyticPixel*) pixval1);
- HSVAnalyticPixel pixel_val_2 = * ((HSVAnalyticPixel*) pixval2);
-
- return (int) (255.0f * (pixel_val_1.light_value - pixel_val_2.light_value));
- }
-
- private static bool rgb_pixel_equal_func(RGBAnalyticPixel? p1, RGBAnalyticPixel? p2) {
- return (p1.equals(p2));
- }
-
- private static uint rgb_pixel_hash_func(RGBAnalyticPixel? pixel_val) {
- return pixel_val.hash_code();
- }
-}
-
-public class RGBHistogramManipulator : Gtk.DrawingArea {
- private enum LocationCode { LEFT_NUB, RIGHT_NUB, LEFT_TROUGH, RIGHT_TROUGH,
- INSENSITIVE_AREA }
- private const int NUB_SIZE = 13;
- private const int NUB_HALF_WIDTH = NUB_SIZE / 2;
- private const int NUB_V_NUDGE = 4;
- private const int TROUGH_WIDTH = 256 + (2 * NUB_HALF_WIDTH);
- private const int TROUGH_HEIGHT = 4;
- private const int TROUGH_BOTTOM_OFFSET = 1;
- private const int CONTROL_WIDTH = TROUGH_WIDTH + 2;
- private const int CONTROL_HEIGHT = 118;
- private const int NUB_V_POSITION = CONTROL_HEIGHT - TROUGH_HEIGHT - TROUGH_BOTTOM_OFFSET
- - (NUB_SIZE - TROUGH_HEIGHT) / 2 - NUB_V_NUDGE - 2;
- private int left_nub_max = 255 - NUB_SIZE - 1;
- private int right_nub_min = NUB_SIZE + 1;
-
- private static Gtk.Widget dummy_slider = null;
- private static Gtk.Widget dummy_frame = null;
- private static Gtk.WidgetPath slider_draw_path = new Gtk.WidgetPath();
- private static Gtk.WidgetPath frame_draw_path = new Gtk.WidgetPath();
- private static bool paths_setup = false;
-
- private RGBHistogram histogram = null;
- private int left_nub_position = 0;
- private int right_nub_position = 255;
- private Gdk.Pixbuf nub_pixbuf = ThemeLoader.load_icon("drag_nub.png");
- private bool is_left_nub_tracking = false;
- private bool is_right_nub_tracking = false;
- private int track_start_x = 0;
- private int track_nub_start_position = 0;
-
- public RGBHistogramManipulator( ) {
- set_size_request(CONTROL_WIDTH, CONTROL_HEIGHT);
-
- if (dummy_slider == null)
- dummy_slider = new Gtk.Scale(Gtk.Orientation.HORIZONTAL, null);
-
- if (dummy_frame == null)
- dummy_frame = new Gtk.Frame(null);
-
- if (!paths_setup) {
- slider_draw_path.append_type(typeof(Gtk.Scale));
- slider_draw_path.iter_add_class(0, "scale");
- slider_draw_path.iter_add_class(0, "range");
-
- frame_draw_path.append_type(typeof(Gtk.Frame));
- frame_draw_path.iter_add_class(0, "default");
-
- paths_setup = true;
- }
-
- add_events(Gdk.EventMask.BUTTON_PRESS_MASK);
- add_events(Gdk.EventMask.BUTTON_RELEASE_MASK);
- add_events(Gdk.EventMask.BUTTON_MOTION_MASK);
-
- button_press_event.connect(on_button_press);
- button_release_event.connect(on_button_release);
- motion_notify_event.connect(on_button_motion);
- }
-
- private LocationCode hit_test_point(int x, int y) {
- if (y < NUB_V_POSITION)
- return LocationCode.INSENSITIVE_AREA;
-
- if ((x > left_nub_position) && (x < left_nub_position + NUB_SIZE))
- return LocationCode.LEFT_NUB;
-
- if ((x > right_nub_position) && (x < right_nub_position + NUB_SIZE))
- return LocationCode.RIGHT_NUB;
-
- if (y < (NUB_V_POSITION + NUB_V_NUDGE + 1))
- return LocationCode.INSENSITIVE_AREA;
-
- if ((x - left_nub_position) * (x - left_nub_position) <
- (x - right_nub_position) * (x - right_nub_position))
- return LocationCode.LEFT_TROUGH;
- else
- return LocationCode.RIGHT_TROUGH;
- }
-
- private bool on_button_press(Gdk.EventButton event_record) {
- LocationCode loc = hit_test_point((int) event_record.x, (int) event_record.y);
-
- switch (loc) {
- case LocationCode.LEFT_NUB:
- track_start_x = ((int) event_record.x);
- track_nub_start_position = left_nub_position;
- is_left_nub_tracking = true;
- return true;
-
- case LocationCode.RIGHT_NUB:
- track_start_x = ((int) event_record.x);
- track_nub_start_position = right_nub_position;
- is_right_nub_tracking = true;
- return true;
-
- case LocationCode.LEFT_TROUGH:
- left_nub_position = ((int) event_record.x) - NUB_HALF_WIDTH;
- left_nub_position = left_nub_position.clamp(0, left_nub_max);
- force_update();
- nub_position_changed();
- update_nub_extrema();
- return true;
-
- case LocationCode.RIGHT_TROUGH:
- right_nub_position = ((int) event_record.x) - NUB_HALF_WIDTH;
- right_nub_position = right_nub_position.clamp(right_nub_min, 255);
- force_update();
- nub_position_changed();
- update_nub_extrema();
- return true;
-
- default:
- return false;
- }
- }
-
- private bool on_button_release(Gdk.EventButton event_record) {
- if (is_left_nub_tracking || is_right_nub_tracking) {
- nub_position_changed();
- update_nub_extrema();
- }
-
- is_left_nub_tracking = false;
- is_right_nub_tracking = false;
-
- return false;
- }
-
- private bool on_button_motion(Gdk.EventMotion event_record) {
- if ((!is_left_nub_tracking) && (!is_right_nub_tracking))
- return false;
-
- if (is_left_nub_tracking) {
- int track_x_delta = ((int) event_record.x) - track_start_x;
- left_nub_position = (track_nub_start_position + track_x_delta);
- left_nub_position = left_nub_position.clamp(0, left_nub_max);
- } else { /* right nub is tracking */
- int track_x_delta = ((int) event_record.x) - track_start_x;
- right_nub_position = (track_nub_start_position + track_x_delta);
- right_nub_position = right_nub_position.clamp(right_nub_min, 255);
- }
-
- force_update();
- return true;
- }
-
- public override bool draw(Cairo.Context ctx) {
- Gtk.Border padding = get_style_context().get_padding(Gtk.StateFlags.NORMAL);
-
- Gdk.Rectangle area = Gdk.Rectangle();
- area.x = padding.left;
- area.y = padding.top;
- area.width = RGBHistogram.GRAPHIC_WIDTH + padding.right;
- area.height = RGBHistogram.GRAPHIC_HEIGHT + padding.bottom;
-
- draw_histogram_frame(ctx, area);
- draw_histogram(ctx, area);
- draw_trough(ctx, area);
- draw_nub(ctx, area, left_nub_position);
- draw_nub(ctx, area, right_nub_position);
-
- return true;
- }
-
- private void draw_histogram_frame(Cairo.Context ctx, Gdk.Rectangle area) {
- // the framed area is inset and slightly smaller than the overall histogram
- // control area
- Gdk.Rectangle framed_area = area;
- framed_area.x += 5;
- framed_area.y += 1;
- framed_area.width -= 8;
- framed_area.height -= 12;
-
- Gtk.StyleContext stylectx = dummy_frame.get_style_context();
- stylectx.save();
-
- stylectx.get_path().append_type(typeof(Gtk.Frame));
- stylectx.get_path().iter_add_class(0, "default");
- stylectx.add_class(Gtk.STYLE_CLASS_TROUGH);
- stylectx.set_junction_sides(Gtk.JunctionSides.TOP | Gtk.JunctionSides.BOTTOM |
- Gtk.JunctionSides.LEFT | Gtk.JunctionSides.RIGHT);
-
- stylectx.render_frame(ctx, framed_area.x, framed_area.y, framed_area.width,
- framed_area.height);
-
- stylectx.restore();
- }
-
- private void draw_histogram(Cairo.Context ctx, Gdk.Rectangle area) {
- if (histogram == null)
- return;
-
- Gdk.Pixbuf histogram_graphic = histogram.get_graphic().copy();
- unowned uchar[] pixel_data = histogram_graphic.get_pixels();
-
- int edge_blend_red = 0;
- int edge_blend_green = 0;
- int edge_blend_blue = 0;
- int body_blend_red = 20;
- int body_blend_green = 20;
- int body_blend_blue = 20;
-
- if (left_nub_position > 0) {
- int edge_pixel_index = histogram_graphic.n_channels * left_nub_position;
- for (int i = 0; i < histogram_graphic.height; i++) {
- int body_pixel_index = i * histogram_graphic.rowstride;
- int row_last_pixel = body_pixel_index + histogram_graphic.n_channels *
- left_nub_position;
- while (body_pixel_index < row_last_pixel) {
- pixel_data[body_pixel_index] =
- (uchar) ((pixel_data[body_pixel_index] + body_blend_red) / 2);
- pixel_data[body_pixel_index + 1] =
- (uchar) ((pixel_data[body_pixel_index + 1] + body_blend_green) / 2);
- pixel_data[body_pixel_index + 2] =
- (uchar) ((pixel_data[body_pixel_index + 2] + body_blend_blue) / 2);
-
- body_pixel_index += histogram_graphic.n_channels;
- }
-
- pixel_data[edge_pixel_index] =
- (uchar) ((pixel_data[edge_pixel_index] + edge_blend_red) / 2);
- pixel_data[edge_pixel_index + 1] =
- (uchar) ((pixel_data[edge_pixel_index + 1] + edge_blend_green) / 2);
- pixel_data[edge_pixel_index + 2] =
- (uchar) ((pixel_data[edge_pixel_index + 2] + edge_blend_blue) / 2);
-
- edge_pixel_index += histogram_graphic.rowstride;
- }
- }
-
- edge_blend_red = 250;
- edge_blend_green = 250;
- edge_blend_blue = 250;
- body_blend_red = 200;
- body_blend_green = 200;
- body_blend_blue = 200;
-
- if (right_nub_position < 255) {
- int edge_pixel_index = histogram_graphic.n_channels * right_nub_position;
- for (int i = 0; i < histogram_graphic.height; i++) {
- int body_pixel_index = i * histogram_graphic.rowstride +
- histogram_graphic.n_channels * 255;
- int row_last_pixel = i * histogram_graphic.rowstride +
- histogram_graphic.n_channels * right_nub_position;
- while (body_pixel_index > row_last_pixel) {
- pixel_data[body_pixel_index] =
- (uchar) ((pixel_data[body_pixel_index] + body_blend_red) / 2);
- pixel_data[body_pixel_index + 1] =
- (uchar) ((pixel_data[body_pixel_index + 1] + body_blend_green) / 2);
- pixel_data[body_pixel_index + 2] =
- (uchar) ((pixel_data[body_pixel_index + 2] + body_blend_blue) / 2);
-
- body_pixel_index -= histogram_graphic.n_channels;
- }
- pixel_data[edge_pixel_index] =
- (uchar) ((pixel_data[edge_pixel_index] + edge_blend_red) / 2);
- pixel_data[edge_pixel_index + 1] =
- (uchar) ((pixel_data[edge_pixel_index + 1] + edge_blend_green) / 2);
- pixel_data[edge_pixel_index + 2] =
- (uchar) ((pixel_data[edge_pixel_index + 2] + edge_blend_blue) / 2);
-
- edge_pixel_index += histogram_graphic.rowstride;
- }
- }
-
- Gdk.cairo_set_source_pixbuf(ctx, histogram_graphic, area.x + NUB_HALF_WIDTH, area.y + 2);
- ctx.paint();
- }
-
- private void draw_trough(Cairo.Context ctx, Gdk.Rectangle area) {
- int trough_x = area.x;
- int trough_y = area.y + (CONTROL_HEIGHT - TROUGH_HEIGHT - TROUGH_BOTTOM_OFFSET - 3);
-
- Gtk.StyleContext stylectx = dummy_slider.get_style_context();
- stylectx.save();
-
- stylectx.get_path().append_type(typeof(Gtk.Scale));
- stylectx.get_path().iter_add_class(0, "scale");
- stylectx.add_class(Gtk.STYLE_CLASS_TROUGH);
-
- stylectx.render_activity(ctx, trough_x, trough_y, TROUGH_WIDTH, TROUGH_HEIGHT);
-
- stylectx.restore();
- }
-
- private void draw_nub(Cairo.Context ctx, Gdk.Rectangle area, int position) {
- Gdk.cairo_set_source_pixbuf(ctx, nub_pixbuf, area.x + position, area.y + NUB_V_POSITION);
- ctx.paint();
- }
-
- private void force_update() {
- get_window().invalidate_rect(null, true);
- get_window().process_updates(true);
- }
-
- private void update_nub_extrema() {
- right_nub_min = left_nub_position + NUB_SIZE + 1;
- left_nub_max = right_nub_position - NUB_SIZE - 1;
- }
-
- public signal void nub_position_changed();
-
- public void update_histogram(Gdk.Pixbuf source_pixbuf) {
- histogram = new RGBHistogram(source_pixbuf);
- force_update();
- }
-
- public int get_left_nub_position() {
- return left_nub_position;
- }
-
- public int get_right_nub_position() {
- return right_nub_position;
- }
-
- public void set_left_nub_position(int user_nub_pos) {
- assert ((user_nub_pos >= 0) && (user_nub_pos <= 255));
- left_nub_position = user_nub_pos.clamp(0, left_nub_max);
- update_nub_extrema();
- }
-
- public void set_right_nub_position(int user_nub_pos) {
- assert ((user_nub_pos >= 0) && (user_nub_pos <= 255));
- right_nub_position = user_nub_pos.clamp(right_nub_min, 255);
- update_nub_extrema();
- }
-}
-