|
| 1 | +const Lang = imports.lang; |
| 2 | +const St = imports.gi.St; |
| 3 | +const Clutter = imports.gi.Clutter; |
| 4 | + |
| 5 | +function BarIndicatorStyle(applet, cols, rows, height) { |
| 6 | + this._init(applet, cols, rows, height); |
| 7 | +} |
| 8 | + |
| 9 | +BarIndicatorStyle.prototype = { |
| 10 | + |
| 11 | + _init: function(applet, cols, rows, height) { |
| 12 | + this.applet = applet; |
| 13 | + this.button = []; |
| 14 | + this.update_grid(cols, rows, height); |
| 15 | + this.switch_id = global.window_manager.connect('switch-workspace', Lang.bind(this, this.update)); |
| 16 | + this.scroll_id = this.applet.actor.connect('scroll-event', Lang.bind(this,this.onMouseScroll)); |
| 17 | + }, |
| 18 | + |
| 19 | + update_grid: function(cols, rows, height) { |
| 20 | + this.cols = cols; |
| 21 | + this.rows = rows; |
| 22 | + this.height = height; |
| 23 | + this.rebuild(); |
| 24 | + }, |
| 25 | + |
| 26 | + cleanup: function() { |
| 27 | + global.window_manager.disconnect(this.switch_id); |
| 28 | + this.applet.actor.disconnect(this.scroll_id); |
| 29 | + }, |
| 30 | + |
| 31 | + onMouseScroll: function(actor, event){ |
| 32 | + if (this.scrollby == 'row') |
| 33 | + this.scrollByRow(event); |
| 34 | + else |
| 35 | + this.scrollByCol(event); |
| 36 | + }, |
| 37 | + |
| 38 | + scrollByCol: function(event) { |
| 39 | + var idx = global.screen.get_active_workspace_index(); |
| 40 | + |
| 41 | + if (event.get_scroll_direction() == 0) idx--; |
| 42 | + else if (event.get_scroll_direction() == 1) idx++; |
| 43 | + |
| 44 | + if(global.screen.get_workspace_by_index(idx) != null) |
| 45 | + global.screen.get_workspace_by_index(idx).activate(global.get_current_time()); |
| 46 | + }, |
| 47 | + |
| 48 | + scrollByRow: function(event) { |
| 49 | + var idx = global.screen.get_active_workspace_index(); |
| 50 | + var numworkspaces = this.rows * this.cols; |
| 51 | + |
| 52 | + var row = Math.floor(idx/this.cols); |
| 53 | + var col = idx % this.cols; |
| 54 | + |
| 55 | + if (event.get_scroll_direction() == 0) { |
| 56 | + row--; |
| 57 | + if (row < 0) { |
| 58 | + row=this.rows-1; |
| 59 | + col--; |
| 60 | + } |
| 61 | + } |
| 62 | + else if (event.get_scroll_direction() == 1) { |
| 63 | + row++; |
| 64 | + if (row >= this.rows) { |
| 65 | + row=0; |
| 66 | + col++; |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + if (col < 0 || col >= this.cols) |
| 71 | + return; |
| 72 | + |
| 73 | + idx = row*this.cols + col; |
| 74 | + |
| 75 | + if(global.screen.get_workspace_by_index(idx) != null) |
| 76 | + global.screen.get_workspace_by_index(idx).activate(global.get_current_time()); |
| 77 | + }, |
| 78 | + |
| 79 | + onRowIndicatorClicked: function(actor, event) { |
| 80 | + if (event.get_button() != 1) return false; |
| 81 | + |
| 82 | + let curws_idx = global.screen.get_active_workspace_index(); |
| 83 | + let curws_row = Math.floor(curws_idx/this.cols); |
| 84 | + let [x, y] = event.get_coords(); |
| 85 | + let [wx, wy] = actor.get_transformed_position(); |
| 86 | + let [w, h] = actor.get_size(); |
| 87 | + y -= wy; |
| 88 | + |
| 89 | + let clicked_row = Math.floor(this.rows*y/h); |
| 90 | + clicked_idx = (clicked_row * this.cols) + (curws_idx % this.cols); |
| 91 | + |
| 92 | + global.screen.get_workspace_by_index(clicked_idx).activate(global.get_current_time()); |
| 93 | + return true; |
| 94 | + }, |
| 95 | + |
| 96 | + onWorkspaceButtonClicked: function(actor, event) { |
| 97 | + if (event.get_button() != 1) return false; |
| 98 | + global.screen.get_workspace_by_index(actor.index).activate(global.get_current_time()); |
| 99 | + }, |
| 100 | + |
| 101 | + setReactivity: function(reactive) { |
| 102 | + for (let i=0; i < this.button.length; ++i) |
| 103 | + this.button[i].set_reactive(reactive); |
| 104 | + }, |
| 105 | + |
| 106 | + rebuild: function() { |
| 107 | + this.applet.actor.destroy_all_children(); |
| 108 | + |
| 109 | + if (this.rows > 1) { |
| 110 | + this.row_indicator = new St.DrawingArea({ reactive: true }); |
| 111 | + this.row_indicator.set_width(this.height/1.75); |
| 112 | + this.row_indicator.connect('repaint', Lang.bind(this, this.draw_row_indicator)); |
| 113 | + this.row_indicator.connect('button-press-event', Lang.bind(this, this.onRowIndicatorClicked)); |
| 114 | + this.applet.actor.add(this.row_indicator); |
| 115 | + } |
| 116 | + |
| 117 | + this.button = []; |
| 118 | + for ( let i=0; i<global.screen.n_workspaces; ++i ) { |
| 119 | + this.button[i] = new St.Button({ name: 'workspaceButton', style_class: 'workspace-button', reactive: true }); |
| 120 | + |
| 121 | + let text = (i+1).toString(); |
| 122 | + let label = new St.Label({ text: text }); |
| 123 | + label.set_style("font-weight: bold"); |
| 124 | + this.button[i].set_child(label); |
| 125 | + this.applet.actor.add(this.button[i]); |
| 126 | + this.button[i].index = i; |
| 127 | + this.button[i].set_height(this.height); |
| 128 | + this.button[i].set_width(this.height*1.25); |
| 129 | + this.button[i].connect('button-release-event', Lang.bind(this, this.onWorkspaceButtonClicked)); |
| 130 | + } |
| 131 | + this.update(); |
| 132 | + }, |
| 133 | + |
| 134 | + update: function() { |
| 135 | + let nworks = this.button.length; |
| 136 | + let active_ws = global.screen.get_active_workspace_index(); |
| 137 | + let active_row = Math.floor(active_ws/this.cols); |
| 138 | + let low = (active_row)*this.cols; |
| 139 | + let high = low + this.cols; |
| 140 | + |
| 141 | + // If the user added or removed workspaces external to this applet then |
| 142 | + // we could end up with a selected workspaces that is out of bounds. Just |
| 143 | + // revert to displaying the last row in that case. |
| 144 | + if (active_ws >= nworks) { |
| 145 | + high = nworks - 1; |
| 146 | + low = high - this.cols; |
| 147 | + } |
| 148 | + |
| 149 | + for (let i=0; i < nworks; ++i) { |
| 150 | + if (i >= low && i < high) this.button[i].show(); |
| 151 | + else this.button[i].hide(); |
| 152 | + |
| 153 | + if (i == active_ws) { |
| 154 | + this.button[i].get_child().set_text((i+1).toString()); |
| 155 | + this.button[i].add_style_pseudo_class('outlined'); |
| 156 | + } |
| 157 | + else { |
| 158 | + this.button[i].get_child().set_text((i+1).toString()); |
| 159 | + this.button[i].remove_style_pseudo_class('outlined'); |
| 160 | + } |
| 161 | + } |
| 162 | + |
| 163 | + if ( this.row_indicator ) { |
| 164 | + this.row_indicator.queue_repaint(); |
| 165 | + } |
| 166 | + }, |
| 167 | + |
| 168 | + draw_row_indicator: function(area) { |
| 169 | + let [width, height] = area.get_surface_size(); |
| 170 | + let themeNode = this.row_indicator.get_theme_node(); |
| 171 | + let cr = area.get_context(); |
| 172 | + |
| 173 | + let base_color = this.get_base_color(); |
| 174 | + let active_color = null; |
| 175 | + let inactive_color = null; |
| 176 | + |
| 177 | + if (this.is_theme_light_on_dark()) { |
| 178 | + active_color = base_color.lighten(); |
| 179 | + inactive_color = base_color.darken(); |
| 180 | + } |
| 181 | + else { |
| 182 | + active_color = base_color.darken().darken(); |
| 183 | + inactive_color = base_color.lighten().lighten(); |
| 184 | + } |
| 185 | + |
| 186 | + let active = global.screen.get_active_workspace_index(); |
| 187 | + let active_row = Math.floor(active/this.cols); |
| 188 | + |
| 189 | + // Catch overflow due to externally added/removed workspaces |
| 190 | + if (active >= this.button.length) active_row = (this.button.length-1) /this.cols; |
| 191 | + |
| 192 | + for ( let i=0; i < this.rows; ++i ) { |
| 193 | + let y = (i+1)*height/(this.rows+1); |
| 194 | + let endx = (width / 10) * 9; |
| 195 | + cr.moveTo(0, y); |
| 196 | + cr.lineTo(endx, y); |
| 197 | + let color = active_row == i ? active_color : inactive_color; |
| 198 | + Clutter.cairo_set_source_color(cr, color); |
| 199 | + cr.setLineWidth(2.0); |
| 200 | + cr.stroke(); |
| 201 | + } |
| 202 | + }, |
| 203 | + |
| 204 | + is_theme_light_on_dark: function() { |
| 205 | + let selected_idx = global.screen.get_active_workspace_index(); |
| 206 | + let unselected_idx = 0; |
| 207 | + if (unselected_idx == selected_idx) unselected_idx = 1; |
| 208 | + |
| 209 | + let selected_txt_color = this.button[selected_idx].get_theme_node().get_color('color'); |
| 210 | + let unselected_txt_color = this.button[unselected_idx].get_theme_node().get_color('color'); |
| 211 | + |
| 212 | + let sel_avg = (selected_txt_color.red + selected_txt_color.green + selected_txt_color.blue)/3; |
| 213 | + let unsel_avg = (unselected_txt_color.red + unselected_txt_color.green + unselected_txt_color.blue)/3; |
| 214 | + return (sel_avg < unsel_avg); |
| 215 | + }, |
| 216 | + |
| 217 | + // All colors we use in this applet are based on this theme defined color. |
| 218 | + // We simply grab the color of a normal, non-outlined workspae button. |
| 219 | + get_base_color: function() { |
| 220 | + let unselected_idx = 0; |
| 221 | + if (unselected_idx == global.screen.get_active_workspace_index()) unselected_idx = 1; |
| 222 | + return this.button[unselected_idx].get_theme_node().get_color('color'); |
| 223 | + } |
| 224 | +}; |
| 225 | + |
0 commit comments