Fix up mouseover handling in the port matrix.
[ardour.git] / gtk2_ardour / port_matrix_component.cc
1 /*
2     Copyright (C) 2002-2009 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <iostream>
21 #include "port_matrix_component.h"
22
23 /** Constructor.
24  *  @param p Port matrix that we're in.
25  */
26 PortMatrixComponent::PortMatrixComponent (PortMatrix* m, PortMatrixBody* b)
27         : _matrix (m),
28           _body (b),
29           _pixmap (0),
30           _render_required (true),
31           _dimension_computation_required (true)
32 {
33         
34 }
35
36 /** Destructor */
37 PortMatrixComponent::~PortMatrixComponent ()
38 {
39         if (_pixmap) {
40                 gdk_pixmap_unref (_pixmap);
41         }
42 }
43
44 void
45 PortMatrixComponent::setup ()
46 {
47         _dimension_computation_required = true;
48         _render_required = true;
49 }
50
51 GdkPixmap *
52 PortMatrixComponent::get_pixmap (GdkDrawable *drawable)
53 {
54         if (_render_required) {
55
56                 if (_dimension_computation_required) {
57                         compute_dimensions ();
58                         _dimension_computation_required = false;
59                 }
60
61                 /* we may be zero width or height; if so, just
62                    use the smallest allowable pixmap */
63                 if (_width == 0) {
64                         _width = 1;
65                 }
66                 if (_height == 0) {
67                         _height = 1;
68                 }
69
70                 /* make a pixmap of the right size */
71                 if (_pixmap) {
72                         gdk_pixmap_unref (_pixmap);
73                 }
74                 _pixmap = gdk_pixmap_new (drawable, _width, _height, -1);
75
76                 /* render */
77                 cairo_t* cr = gdk_cairo_create (_pixmap);
78                 render (cr);
79                 cairo_destroy (cr);
80
81                 _render_required = false;
82         }
83
84         return _pixmap;
85 }
86
87 void
88 PortMatrixComponent::set_source_rgb (cairo_t *cr, Gdk::Color const & c)
89 {
90         cairo_set_source_rgb (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p());
91 }
92
93 void
94 PortMatrixComponent::set_source_rgba (cairo_t *cr, Gdk::Color const & c, double a)
95 {
96         cairo_set_source_rgba (cr, c.get_red_p(), c.get_green_p(), c.get_blue_p(), a);
97 }
98
99 std::pair<uint32_t, uint32_t>
100 PortMatrixComponent::dimensions ()
101 {
102         if (_dimension_computation_required) {
103                 compute_dimensions ();
104                 _dimension_computation_required = false;
105         }
106
107         return std::make_pair (_width, _height);
108 }
109
110 std::pair<std::string, double>
111 PortMatrixComponent::display_port_name (cairo_t* cr, std::string const &n, double avail) const
112 {
113         /* XXX hopefully there exists a more efficient way of doing this */
114         
115         Glib::ustring name = Glib::ustring (n).uppercase ();
116         bool abbreviated = false;
117         uint32_t width = 0;
118                 
119         while (1) {
120                 if (name.length() <= 2) {
121                         break;
122                 }
123                         
124                 cairo_text_extents_t ext;
125                 cairo_text_extents (cr, name.c_str(), &ext);
126                 if (ext.width < avail) {
127                         width = ext.width;
128                         break;
129                 }
130                         
131                 if (abbreviated) {
132                         name = name.substr (0, name.length() - 2) + ".";
133                 } else {
134                         name = name.substr (0, name.length() - 1) + ".";
135                         abbreviated = true;
136                 }
137         }
138
139         return std::make_pair (name, width);
140 }