summaryrefslogtreecommitdiff
path: root/src/user/raleigh/w/colorpicker.cpp
blob: 281eaafb97d508cfc240305389caaab30bd1e5f6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <raleigh/w/colorpicker.h>

namespace raleigh {
  colorpicker::colorpicker(_pixel_t default_color, uint8_t resolution)
    : picked_color(default_color), resolution(resolution),
      inv_res(256 / resolution) {
    size = coord(inv_res * 2, inv_res * 2);
    closest_opaque = this;
  }

  __attribute__ ((pure))
  _pixel_t colorpicker::get_picked_color() {
    return picked_color;
  }

  void colorpicker::paint(_pixel_t *pixbuf, uint32_t pitch) {
    _pixel_t *pb_ptr = pixbuf + window_offset.y * pitch + window_offset.x;
    for (uint16_t b = 0; b < inv_res; ++b)
      for (uint16_t g = 0; g < inv_res; ++g)
        pb_ptr[b * pitch + g] = (_pixel_t){.r = picked_color.r, .g = g * resolution, .b = b * resolution};
    pb_ptr += inv_res;
    for (uint16_t r = 0; r < inv_res; ++r)
      for (uint16_t b = 0; b < inv_res; ++b)
        pb_ptr[r * pitch + b] = (_pixel_t){.r = r * resolution, .g = picked_color.g, .b = b * resolution};
    pb_ptr += inv_res * (pitch - 1);
    for (uint16_t g = 0; g < inv_res; ++g)
      for (uint16_t r = 0; r < inv_res; ++r)
        pb_ptr[g * pitch + r] = (_pixel_t){.r = r * resolution, .g = g * resolution, .b = picked_color.b};
    pb_ptr += inv_res;
    for (uint16_t y = 0; y < inv_res; ++y)
      for (uint16_t x = 0; x < inv_res; ++x)
        pb_ptr[y * pitch + x] = picked_color;
  }

  void colorpicker::set_picked_color(_pixel_t c) {
    picked_color = c;
    if (w)
      w->notify_needs_paint(*this);
  }

  void colorpicker::handle_click(coord window_coords, enum mouse_packet::mouse_button click_type, bool up) {
    if (up || (click_type != mouse_packet::LEFT))
      return;
    window_coords.x -= window_offset.x;
    window_coords.y -= window_offset.y;
    if ((window_coords.x < inv_res) && (window_coords.y < inv_res)) {
      selected = R;
      picked_color.g = window_coords.x * resolution;
      picked_color.b = window_coords.y * resolution;
    }
    else if (window_coords.y < inv_res) {
      selected = G;
      picked_color.b = (window_coords.x - inv_res) * resolution;
      picked_color.r = window_coords.y * resolution;
    }
    else if (window_coords.x < inv_res) {
      selected = B;
      picked_color.r = window_coords.x * resolution;
      picked_color.g = (window_coords.y - inv_res) * resolution;
    }
    w->notify_needs_paint(*this);
    w->notify_wants_movements(*this, mouse_packet::LEFT);
  }

  void colorpicker::notify_has_opaque_parent(widget *parent) {}

  void colorpicker::on_mouse_move(coord window_coords) {
    int32_t x = window_coords.x - window_offset.x;
    int32_t y = window_coords.y - window_offset.y;
    switch (selected) {
    case R:
      if (x >= inv_res)
        x = inv_res - 1;
      if (x < 0)
        x = 0;
      if (y >= inv_res)
        y = inv_res - 1;
      if (y < 0)
        y = 0;
      picked_color.g = x * resolution;
      picked_color.b = y * resolution;
      break;
    case G:
      if (x < inv_res)
        x = inv_res;
      if (x >= inv_res * 2)
        x = inv_res * 2 - 1;
      if (y >= inv_res)
        y = inv_res - 1;
      if (y < 0)
        y = 0;
      picked_color.b = x * resolution;
      picked_color.r = y * resolution;
      break;
    case B:
      if (x >= inv_res)
        x = inv_res - 1;
      if (x < 0)
        x = 0;
      if (y < inv_res)
        y = inv_res;
      if (y >= inv_res * 2)
        y = inv_res * 2 - 1;
      picked_color.r = x * resolution;
      picked_color.g = y * resolution;
      break;
    }
    w->notify_needs_paint(*this);
  }
}