/* Copyright (C) 2012 2014 2015 Johan Mattsson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ using Cairo; using Math; namespace BirdFont { public class Expander : GLib.Object { private static const double HEADLINE_MARGIN = 4; public double x = 7; public double y = 5; public double scroll = 0; public double w = 6; public double h = 5; public double margin = 0; protected double opacity = 0; protected bool active = false; public Gee.ArrayList tool; bool persist = false; bool unique = false; double content_height = 0; string? headline; Text title; public bool visible = true; Surface? cached = null; public Expander (string? headline = null) { this.headline = headline; title = new Text (); if (headline != null) { title.set_text ((!) headline); } tool = new Gee.ArrayList (); } public void clear_cache () { cached = null; } public void set_headline (Text h) { headline = h.get_text (); title = h; } public double get_content_height () { return content_height; } /** Returns true if tools can be used with the current canvas after * they have been selectes and false if they are a commands to be executed. */ public bool is_persistent () { return persist; } /** Returns true if all other tools in thid expander should be deselected * when a tool is selected. */ public bool is_unique () { return unique; } public void set_persistent (bool p) { persist = p; } public void set_unique (bool u) { unique = u; } public void update_tool_position () { double scale = Toolbox.get_scale (); double margin_small = 5 * scale; double xt = x; double yt = y + margin_small; // + scroll bool new_row = false; bool has_visible_tools = false; Tool previous; bool first_row; foreach (Tool t in tool) { if (t.tool_is_visible ()) { has_visible_tools = true; break; } } if (!has_visible_tools) { content_height = 0; return; } foreach (Tool t in tool) { if (t is ZoomBar) { t.w = Toolbox.allocation_width * scale; t.h = 10 * scale; // 7 } else if (t is LabelTool) { t.w = Toolbox.allocation_width * scale; t.h = 22 * scale; } else if (t is FontName) { t.w = Toolbox.allocation_width * scale; t.h = 20 * scale; } else if (t is KerningRange) { t.w = Toolbox.allocation_width * scale; t.h = 17 * scale; } else if (t is LayerLabel) { t.w = Toolbox.allocation_width * scale; t.h = 21 * scale; } else if (t is ColorPicker) { t.w = Toolbox.allocation_width * scale; t.h = 5 * ((ColorPicker) t).bar_height; } else { t.w = 33 * scale; t.h = (33 / 1.11) * scale; } } if (tool.size > 0) { content_height = tool.get (0).h + margin_small; } else { content_height = 0; } if (headline != null && tool.size > 0) { yt += 17 * scale + HEADLINE_MARGIN; content_height += 17 * scale + HEADLINE_MARGIN; } if (tool.size > 0) { previous = tool.get (0); first_row = true; foreach (Tool t in tool) { if (t.tool_is_visible ()) { new_row = xt + t.w > Toolbox.allocation_width - 7 * scale; if (t is ZoomBar) { t.x = xt; t.y = yt; yt += t.h + 7 * scale; previous = t; continue; } if (previous is ZoomBar) { content_height += t.h; } if (new_row && !first_row) { content_height += previous.h; xt = x; yt += previous.h; if (!(t is LabelTool) && !(previous is LayerLabel)) { yt += 7 * scale; } if (!(previous is LayerLabel)) { content_height += margin_small; } } t.x = xt; t.y = yt; xt += t.w + 7 * scale; if (previous is ZoomBar) { content_height += 7 * scale; } previous = t; first_row = false; } } content_height += 5 * scale; } if (unlikely (content_height < 0)) { warning (@"content_height < 0"); } } public void set_scroll (double scroll) { this.scroll = scroll; } public void set_offset (double ty) { y = ty; update_tool_position (); } public void redraw () { Toolbox.redraw_tool_box (); } public void add_tool (Tool t, int position = -1) { if (position < 0) { tool.add (t); } else { return_if_fail (position <= tool.size); tool.insert (position, t); } t.redraw_tool.connect (() => { cached = null; }); update_tool_position (); t.select_action.connect ((selected) => { MainWindow.get_toolbox ().redraw ((int) x, (int) y, (int) w + 300, (int) (h + margin)); if (is_unique ()) { foreach (var deselected in tool) { if (selected.get_id () != deselected.get_id ()) { deselected.set_selected (false); } } } if (!selected.new_selection && selected.persistent) { if (is_persistent ()) { selected.set_selected (true); } else { selected.set_selected (false); } } selected.new_selection = false; }); } public bool is_over (double xp, double yp) { double yt = y + scroll + 2; return yt - 7 <= yp <= yt + 7 && xp < 17; } public bool set_active (bool a) { bool r = (active != a); opacity = (a) ? 1 : 0; active = a; return r; } public void cache () { if (cached == null) { Surface workbench = Screen.create_background_surface (1, 1); Context context = new Context (workbench); draw (context); } } public void draw (Context cr) { Surface cache; if (unlikely (cached == null)) { Context cc; double text_height = 17 * Toolbox.get_scale (); double offset_y = 0; cache = Screen.create_background_surface (Toolbox.allocation_width, (int) (h + content_height)); cc = new Context (cache); cc.scale(Screen.get_scale(), Screen.get_scale()); if (tool.size > 0 && headline != null) { Theme.text_color (title, "Text Tool Box"); title.set_font_size (text_height); title.draw_at_top (cc, x, 0); offset_y = text_height + HEADLINE_MARGIN; } draw_content (cc, offset_y); cached = (!) cache; } if (cached != null) { cache = (!) cached; cr.set_antialias (Cairo.Antialias.NONE); Screen.paint_background_surface (cr, cache, 0, (int) (y + scroll)); } } public void draw_content (Context cr, double text_end) { double offset_y = 0; double offset_x = 0; update_tool_position (); if (tool.size > 0) { offset_x = tool.get (0).x; offset_y = tool.get (0).y - text_end; } cr.save (); foreach (Tool t in tool) { if (t.tool_is_visible ()) { t.draw_tool (cr, offset_x - x, offset_y); } } cr.restore (); } } }