diff options
Diffstat (limited to 'bin/subtle-contrib/ruby/merger.rb')
-rw-r--r-- | bin/subtle-contrib/ruby/merger.rb | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/bin/subtle-contrib/ruby/merger.rb b/bin/subtle-contrib/ruby/merger.rb new file mode 100644 index 0000000..30839ac --- /dev/null +++ b/bin/subtle-contrib/ruby/merger.rb @@ -0,0 +1,292 @@ +#!/usr/bin/ruby +# +# @file Merger +# +# @copyright (c) 2011, Christoph Kappel <unexist@dorfelite.net> +# @version $Id$ +# +# This program can be distributed under the terms of the GNU GPLv2. +# See the file COPYING for details. +# +# Select and tag/untag visible views of current client window +# +# Colors: +# +# Focus - Currently selected view +# View - Other views +# Occupied - Views client is visible +# Urgent - Selected views +# +# Keys: +# +# Left, Up - Move to left +# Right, Down - Move to right +# Escape - Hide/exit +# Space - Select view +# Return - Tag/untag selected views and exit hide/exit +# +# http://subforge.org/projects/subtle-contrib/wiki/Positioner +# + +require "singleton" + +begin + require "subtle/subtlext" +rescue LoadError + puts ">>> ERROR: Couldn't find subtlext" + exit +end + +# Check for subtlext version +major, minor, teeny = Subtlext::VERSION.split(".").map(&:to_i) +if(major == 0 and minor == 10 and 3006 > teeny) + puts ">>> ERROR: merger needs at least subtle `0.10.3006' (found: %s)" % [ + Subtlext::VERSION + ] + exit +end + +# Merger class +module Subtle # {{{ + module Contrib # {{{ + class Merger # {{{ + include Singleton + + # Default values + @@font = "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*" + + # Singleton methods + + ## fonts {{{ + # Set font strings + # @param [String] fonts Fonts array + ## + + def self.font=(font) + @@font = font + end # }}} + + ## run {{{ + # Run expose + ## + + def self.run + self.instance.run + end # }}} + + # Instance methods + + ## initialize {{{ + # Create expose instance + ## + + def initialize + # Values + @colors = Subtlext::Subtle.colors + @merged = {} + @backup = {} + + # Create main window + @win = Subtlext::Window.new(:x => 0, :y => 0, :width => 1, :height => 1) do |w| + w.name = "Merger" + w.font = @@font + w.foreground = @colors[:title_fg] + w.background = @colors[:title_bg] + w.border_size = 0 + end + + # Font metrics + @font_height = @win.font_height + 6 + @font_y = @win.font_y + + # Handler + @win.on :key_down, method(:key_down) + @win.on :draw, method(:redraw) + end # }}} + + ## run {{{ + # Show and run positioner + ## + + def run + update + show + hide + end # }}} + + private + + ## key_down {{{ + # Key down handler + # @param [String] key Pressed key + ## + + def key_down(key) + ret = true + + case key + when :left, :up # {{{ + idx = @views.index(@selected) + idx -= 1 if(1 < idx) + @selected = @views[idx] # }}} + when :right, :down # {{{ + idx = @views.index(@selected) + idx += 1 if(idx < (@views.size - 1)) + @selected = @views[idx] # }}} + when :space # {{{ + if(@merged[@current.name].include?(@selected)) + @merged[@current.name].delete(@selected) + else + @merged[@current.name] << @selected + end # }}} + + p @merged + when :return # {{{ + # Restore tags or update + if(@merged[@current.name].empty?) + @merged.delete(@current.name) + @current.tags = @backup[@current.name] + else + @current.tags = @merged[@current.name].inject( + @backup[@current.name]) { |r, v| r | v.tags } + end + + ret = false # }}} + when :escape # {{{ + @merged.delete(@current.name) + ret = false # }}} + end + + redraw(@win) if(ret) + + ret + end # }}} + + ## update # {{{ + # Update clients and windows + ## + + def update + @current = Subtlext::View.current + @views = Subtlext::View.all.select { |v| v != @current } + @selected = @views.first + + @views.unshift(@current) + + # Backup tags of current view + unless(@backup.keys.include?(@current.name)) + @backup[@current.name] = @current.tags + end + + # Create empty array + unless(@merged.keys.include?(@current.name)) + @merged[@current.name] = [] + end + + arrange + end # }}} + + ## arrange {{{ + # Arrange window and subwindows + ## + + def arrange + geo = Subtlext::Screen.current.geometry + width = geo.width * 50 / 100 #< Max width + height = @font_height + wx = 0 + wy = 0 + len = 0 + wwidth = 0 + + # Arrange client windows + @views.each_with_index do |v, i| + len = @win.font_width(v.name) + 6 + + # Wrap lines + if(wx + len > width) + wwidth = wx if(wx > wwidth) + wx = 0 + wy += @font_height + end + + wx += len + end + + # Update geometry + width = 0 == wwidth ? wx : wwidth + height += wy + x = geo.x + ((geo.width - width) / 2) + y = geo.y + ((geo.height - height) / 2) + + @win.geometry = [ x , y, width, height ] + end # }}} + + ## redraw {{{ + # Redraw window content + # @param [Window] w Window instance + ## + + def redraw(w) + @win.clear + + wx = 0 + wy = 0 + len = 0 + + @views.each_with_index do |v, i| + len = @win.font_width(v.name) + 6 + + # Select color + if(v == @selected) + fg = @colors[:focus_fg] + bg = @colors[:focus_bg] + elsif(v == @current) + fg = @colors[:occupied_fg] + bg = @colors[:occupied_bg] + else + fg = @colors[:unoccupied_fg] + bg = @colors[:unoccupied_bg] + end + + if(@merged[@current.name].include?(v)) + fg = @colors[:urgent_fg] + end + + @win.draw_rect(wx, wy, len, @font_height, bg, true) + @win.draw_text(wx + 3, wy + @font_y + 3, v.name, fg) + + wx += len + end + end # }}} + + ## show {{{ + # Show launcher + ## + + def show + @win.show + end # }}} + + ## hide # {{{ + # Hide launcher + ## + + def hide + @win.hide + end # }}} + + end # }}} + end # }}} +end # }}} + +# Implicitly run +if(__FILE__ == $0) + # Set font + #Subtle::Contrib::Merger.font = + # "xft:DejaVu Sans Mono:pixelsize=80:antialias=true" + + Subtle::Contrib::Merger.run +end + +# vim:ts=2:bs=2:sw=2:et:fdm=marker |