24 #ifndef CRN_USING_GTKMM3
30 using namespace GtkCRN;
36 actions(Gtk::ActionGroup::create(
"drawing panel"))
38 #ifndef CRN_USING_GTKMM3
41 actions->get_action(
"drawing-panel-background")->set_short_label(
_(
"Background"));
42 actions->get_action(
"drawing-panel-background")->set_is_important();
43 bg_act->set_color(Gdk::Color(
"white"));
44 bg_act->signal_changed().connect(sigc::mem_fun(
this, &Gtk::Widget::queue_draw));
48 actions->get_action(
"drawing-panel-foreground")->set_short_label(
_(
"Foreground"));
49 actions->get_action(
"drawing-panel-foreground")->set_is_important();
50 fg_act->set_color(Gdk::Color(
"black"));
51 fg_act->signal_changed().connect(sigc::mem_fun(
this, &Gtk::Widget::queue_draw));
60 actions->add(thick_act);
61 thick_act->get_adjustment().configure(thickness, 0.2, 20, 0.1, 1, 1);
62 thick_act->signal_changed().connect(sigc::mem_fun(
this, &DrawingPanel::on_thickness_set));
64 std::vector<Glib::ustring> icons;
65 icons.push_back(
"line05");
66 icons.push_back(
"line3");
67 icons.push_back(
"line1");
68 icons.push_back(
"line2");
69 icons.push_back(
"line3");
70 thick_act->set_icons(icons);
73 add_events(Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON_MOTION_MASK);
74 signal_button_press_event().connect(sigc::mem_fun(
this, &DrawingPanel::on_button_press));
75 signal_motion_notify_event().connect(sigc::mem_fun(
this, &DrawingPanel::on_motion));
76 #ifdef CRN_USING_GTKMM3
77 signal_draw().connect(sigc::mem_fun(
this, &DrawingPanel::on_expose));
79 signal_expose_event().connect(sigc::mem_fun(
this, &DrawingPanel::on_expose));
94 throw Glib::OptionError(Glib::OptionError::BAD_VALUE, Glib::ustring(
"void DrawingPanel::set_zoom(double z): ") +
_(
"null or negative zoom value."));
110 #ifdef CRN_USING_GTKMM3
118 return bg_act->get_color();
125 #ifdef CRN_USING_GTKMM3
132 bg_act->set_color(col);
139 #ifdef CRN_USING_GTKMM3
147 return fg_act->get_color();
154 #ifdef CRN_USING_GTKMM3
161 fg_act->set_color(col);
170 int l = std::numeric_limits<int>::max(), t = std::numeric_limits<int>::max(), r = 0, b = 0;
171 for (
const std::vector<crn::Point2DDouble> &stroke : stroke_list)
175 int pl = int(floor(pnt.X));
176 int pt = int(floor(pnt.Y));
177 int pr = int(ceil(pnt.X));
178 int pb = int(ceil(pnt.Y));
185 if ((r == 0) || (b == 0))
187 return Glib::RefPtr<Gdk::Pixbuf>(
nullptr);
189 int border = int(ceil(thickness));
192 l -= border;
if (l < 0) l = 0;
193 t -= border;
if (t < 0) t = 0;
194 Cairo::RefPtr<Cairo::ImageSurface> surf(Cairo::ImageSurface::create(Cairo::FORMAT_RGB24, r, b));
195 Cairo::RefPtr<Cairo::Context> cr(Cairo::Context::create(surf));
196 #ifdef CRN_USING_GTKMM3
199 cr->set_source_rgb(bg_act->get_color().get_red_p(), bg_act->get_color().get_green_p(), bg_act->get_color().get_blue_p());
203 #ifdef CRN_USING_GTKMM3
206 cr->set_source_rgb(fg_act->get_color().get_red_p(), fg_act->get_color().get_green_p(), fg_act->get_color().get_blue_p());
208 cr->set_line_join(Cairo::LINE_JOIN_ROUND);
209 cr->set_line_cap(Cairo::LINE_CAP_ROUND);
210 cr->set_line_width(thickness);
211 for (
const std::vector<crn::Point2DDouble> &stroke : stroke_list)
215 cr->move_to(stroke.front().X, stroke.front().Y);
216 for (
size_t i = 1; i < stroke.size(); ++i)
218 cr->line_to(stroke[i].X, stroke[i].Y);
224 surf->write_to_png(tmpname.
CStr());
230 Glib::RefPtr<Gdk::Pixbuf> fpb(Gdk::Pixbuf::create_subpixbuf(pb, l, t, r - l, b - t));
237 bool DrawingPanel::draw()
239 Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
240 #ifdef CRN_USING_GTKMM3
243 cr->set_source_rgb(bg_act->get_color().get_red_p(), bg_act->get_color().get_green_p(), bg_act->get_color().get_blue_p());
247 #ifdef CRN_USING_GTKMM3
250 cr->set_source_rgb(fg_act->get_color().get_red_p(), fg_act->get_color().get_green_p(), fg_act->get_color().get_blue_p());
252 cr->set_line_join(Cairo::LINE_JOIN_ROUND);
253 cr->set_line_cap(Cairo::LINE_CAP_ROUND);
254 cr->set_line_width(thickness * zoom);
255 for (
const std::vector<crn::Point2DDouble> &stroke : stroke_list)
259 cr->move_to(stroke.front().X * zoom, stroke.front().Y * zoom);
260 for (
size_t i = 1; i < stroke.size(); ++i)
262 cr->line_to(stroke[i].X * zoom, stroke[i].Y * zoom);
274 bool DrawingPanel::on_button_press(GdkEventButton *ev)
276 stroke_list.push_back(std::vector<crn::Point2DDouble>());
285 bool DrawingPanel::on_motion(GdkEventMotion *ev)
296 #ifdef CRN_USING_GTKMM3
297 bool DrawingPanel::on_expose(
const Cairo::RefPtr<Cairo::Context> &)
299 bool DrawingPanel::on_expose(GdkEventExpose *ev)
309 void DrawingPanel::modify_thickness(
double val)
314 #ifdef CRN_USING_GTKMM3
317 thick_act->get_adjustment().set_value(thickness);
323 void DrawingPanel::on_thickness_set()
325 #ifdef CRN_USING_GTKMM3
328 thickness = thick_act->get_adjustment().get_value();
DrawingPanel()
Constructor.
Glib::RefPtr< Gdk::Pixbuf > create_image()
Renders the panel to a Pixbuf.
Glib::RefPtr< Gdk::Pixbuf > PixbufFromFile(const crn::Path &p)
Creates a Gdk::Pixbuf from a file.
static Glib::RefPtr< ScaleAction > create()
Creates a blank ScaleAction.
Gdk::Color get_background() const
Gets the background color.
void set_zoom(double z)
Sets the zoom level.
void set_background(const Gdk::Color &col)
Sets the background color.
const char * CStr() const noexcept
Conversion to UTF8 cstring.
void clear()
Clears the panel.
A convenience class for file paths.
static Glib::RefPtr< ColorAction > create()
Creates a blank ColorAction.
static void Rm(const Path &name)
Removes a file.
void set_foreground(const Gdk::Color &col)
Sets the foreground color.
Gdk::Color get_foreground() const
Gets the foreground color.