view subtly/browser.rb @ 18:ccd7fc8f1cb5

Added jump implementation
author unexist
date Fri, 22 Jan 2010 13:09:09 +0100
parents ba26532e98c7
children c083232ced42
line wrap: on
line source
 ##
 # @package subtly
 #
 # @file Browser class
 # @author Christoph Kappel <unexist@dorfelite.net>
 # @version $Id: subtly/browser.rb,v 18 1264162149.0-3600 unexist $
 #
 # This program can be distributed under the terms of the GNU GPL.
 ##
 
require "subtly/glib"
require "subtly/gtk"
require "subtly/gdk"
require "subtly/webkit"

module Subtly
  class Browser < Subtly::Gtk::Runner
    LIMIT = 80 #< Limit url length in bar

    ## initialize {{{
    # Create a new browser
    #
    # @return [Object] New browser
    ##

    def initialize
      super

      # Init
      @mode     = :command
      @keys     = {}
      @keychain = ""
      @jumpbuf  = ""

      # Create widgets
      @win      = Subtly::Gtk::Window.new
      @scrolled = Subtly::Gtk::Scrolled.new
      @info     = Subtly::Gtk::Label.new(true, true)
      @status   = Subtly::Gtk::Label.new(true, false)
      @page   = Subtly::Gtk::Label.new(true, false)
      @input    = Subtly::Gtk::Entry.new(false)
      #@list     = Subtly::Gtk::List.new
      @vbox1    = Subtly::Gtk::Box.new(:vbox, false, 0)
      @vbox2    = Subtly::Gtk::Box.new(:vbox, false, 0)
      @hbox     = Subtly::Gtk::Box.new(:hbox, false, 5)
      @webkit   = Subtly::Webkit.new

      # Options
      @win.size  = [ 800, 600 ]
      @win.title = "Subtly"
      @win.klass = [ "Browser", "Subtly" ]

      @win.background    = "#000000"
      @info.foreground   = "#ffffff"
      @status.foreground = "#ffffff"
      @input.foreground  = "#000000"
      @input.background  = "#ffffff"
      @page.foreground = "#ffffff"
      @page.background = "#0000ff"
      @webkit.focusable  = false
      @input.editable    = false
      @input.focusable   = false
      @input.length      = LIMIT
      @info.alignment    = [ 0.0, 0.0 ]
      @status.alignment  = [ 1.0, 0.0 ]

      # Containers
      @win.add(@vbox1)
      @scrolled.add(@webkit)

      # Boxes
      @vbox1.add(@scrolled, true,  true,  0)
      @vbox1.add(@hbox,     false, true,  0)
      @hbox.add(@info,      true,  true,  5)
      @hbox.add(@status,    true,  true,  5)
      @hbox.add(@page,    false, true,  5)
      #@vbox2.add(@list,     false, true, 0)
      @vbox2.add(@input,    false, true,  0)
      @vbox1.add(@vbox2,    false, true,  0)

      # Signals
      @win.connect("destroy",                  method(:win_destroy).to_proc,     nil)
      @win.connect("key-press-event",          method(:win_keypress).to_proc,    nil)

      @webkit.connect("load-started",          method(:webkit_started).to_proc,  nil)
      @webkit.connect("load-finished",         method(:webkit_finished).to_proc, nil)
      @webkit.connect("load-progress-changed", method(:webkit_progress).to_proc, nil)
      @webkit.connect("title-changed",         method(:webkit_title).to_proc,    nil)
      @webkit.connect("scroll-event",          method(:webkit_scroll).to_proc,   nil)
      @webkit.connect("hovering-over-link",    method(:webkit_hover).to_proc,    nil)
      
      @win.show_all
      #@list.hide
    end # }}}

    ## uri= {{{
    # Set browser uri
    #
    # @param  [String, #read]  uri  Uri to load
    ##

    def uri=(uri)
      @webkit.uri  = uri
      @info.text   = format_status(uri[0..LIMIT])
      @page.text = "Top"
    end # }}}

    ## add_keys {{{
    # Add keys hash
    #
    # @param  [Hash, #read]  hash  Keys hash
    ##

    def add_keys(hash)
      hash.each do |v, k|
        # Just make a symbol from keys an store it
        @keys[v.to_sym] = k
      end
    end # }}}

    # Customization

    ## format_status {{{
    # Set status text
    #
    # @param  [String, #read]  str  Status text
    ##

    def format_status(str)
      "%s" % [ str ]
    end # }}}

    ## format_meter {{{
    # Draw status meter
    #
    # @param  [Fixnum, #read]  progress  Load progress in percent
    # @param  [Fixnum, #read]  width     Width of the meter
    ##

    def format_meter(progress, width = 14)
      times = (progress * width) / 100

      "[%s>%s]" % [ "=" * times, " " * (width - times) ]
    end # }}}

    ## format_page {{{
    # Draw page meter
    #
    # @param  [String, #read]  page  Page position in percent
    ##

    def format_page(page)
      case page
        when 0..2    then "Top"
        when 98..100 then "Bot"
        else "%d%%" % [ page ]
      end
    end # }}}
    
    private

    # commands {{{
    def commands(sym)
      case sym
        when :SubtlyUriOpen then
          @input.text     = ":open "
          @input.editable = true
          @mode = :uri
        when :SubtlyUriEdit then
          @input.text = ":open %s" % [ @webkit.uri ]
          @input.editable = true
          @mode = :uri
        when :SubtlyModeInsert then
          @mode             = :insert
          @webkit.focusable = true
          @input.text       = "-- INSERT --"
        when :SubtlyModeCommand then
          @mode             = :command
          @webkit.focusable = false
          @input.text       = ""
        when :SubtlyBrowserBack then
          @webkit.back
        when :SubtlyBrowserForward then
          @webkit.forward
        when :SubtlyScrollTop
          @scrolled.vadjust = 0.0
          @page.text        = format_page(0)
        when :SubtlyScrollBottom
          @scrolled.vadjust = 1.0
          @page.text        = format_page(100)
        when :SubtlyQuit then
          Subtly::Gtk::Runner.ffi_quit 
      end
    end # }}}

    # Callbacks

    # win_destroy # {{{
    def win_destroy(widget, arg)
      Subtly::Gtk::Runner.ffi_quit 
    end # }}}

    # win_keypress {{{
    def win_keypress(widget, arg)
      event = Subtly::Gdk::EventKey.new(arg)

      # Handle keys
      case event[:keyval]
        when Subtly::Gdk::Keys[:escape]
          case @mode
            when :uri then
              @mode           = :command
              @input.editable = false
              @input.text     = ""
            when :command then
              @keychain = ""
              return
            when :insert then
              @mode             = :command
              @webkit.focusable = false
              @input.text       = ""
              @keychain         = ""
          end
        when Subtly::Gdk::Keys[:return]
          case @mode
            when :uri then
              uri             = @input.text.gsub(":open ", "")
              uri             = "http://" + uri unless(uri.include?("http://"))
              @webkit.uri     = uri
              @info.text      = uri[0..LIMIT]
              @input.editable = false
              @input.text     = ""
            when :jump then
              uri         = @keys[@keychain.to_sym]
              uri         = "http://" + uri unless(uri.include?("http://"))
              uri         = uri.gsub("%s", @jumpbuf)

              @webkit.uri = uri
              @info.text  = uri[0..LIMIT]
              @jumpbuf    = ""
              @keychain   = ""
              @mode       = :command
          end
        when Subtly::Gdk::Keys[:backspace] then
          case @mode
            when :uri
             if(":open " != @input.text)
              @input.text = @input.text.chop
            end
          end
        else
          case @mode
            when :uri then
              @input << event[:string]
            when :jump then
              @jumpbuf << event[:string]

              @input.text = ":open %s" % [ @keys[@keychain.to_sym].gsub("%s", @jumpbuf) ]
            else
              @keychain << event[:string]

              if(@keys.include?(@keychain.to_sym))
                # Check if command is a jump
                if("_" == event[:string])
                  @mode = :jump
                  @input.text = ":open %s" % [ @keys[@keychain.to_sym].gsub("%s", @jumpbuf) ]
                else
                  commands(@keys[@keychain.to_sym])
                  @keychain = ""
                end
              end
          end 
      end
         
      puts "Key: %s=%d, state=%d, modifier=%d" % [ 
        event[:string], event[:keyval], event[:state], event[:is_modifier]
      ]
    end # }}}

    # webkit_started {{{
    def webkit_started(widget, arg)
      @status.text = format_meter(0)
    end # }}}

    # webkit_finished {{{
    def webkit_finished(widget, arg)
      @status.text = ""
    end # }}}

    # webkit_progress {{{
    def webkit_progress(widget, arg, data)
      @status.text = format_meter(arg.to_i)
    end # }}}

    # webkit_title {{{
    def webkit_title(widget, arg1, arg2, data)
      title = arg2.read_string

      @win.title = "Subtly: %s" % [ title ]
    end # }}}

    # webkit_scroll {{{
    def webkit_scroll(widget, arg1, data)
      page = (@scrolled.vadjust * 100).to_i

      @page.text = format_page(page)
    end # }}}

    # webkit_hover {{{
    def webkit_hover(widget, arg1, arg2, data)
      begin #< Hover start
        uri        = arg2.read_string
        @info.text = format_status("Link: %s" % [ uri[0..LIMIT] ])
      rescue #< Hover end
        @info.text = format_status(@webkit.uri[0..LIMIT])
      end
    end # }}}
  end
end