class Etti::LabelLayout

Constants

SCALE_MAX
SCALE_MIN

Attributes

backBuffer[R]
centerX[RW]
centerY[RW]
elementDataData[R]
elements[RW]
scale[RW]

Public Class Methods

new(propertyEditors) click to toggle source
Calls superclass method
# File lib/etti/ui/label-layout.rb, line 15
def initialize propertyEditors
    super()
    @propertyEditors = propertyEditors
    @elements = []
    @selectedElement = nil

    @area = Gtk::DrawingArea.new
    add @area
    # I don't use the integrated double buffering, cause it flickers
    # I can do it better myself
    @area.double_buffered = false
    @backBuffer = nil
    $colors = Etti::Colors.new

    self.drag_dest_set :all, [['elements2area', :same_app, 123]], :copy


    @area.add_events Gdk::Event::Mask::SCROLL_MASK |
                    Gdk::Event::Mask::BUTTON_PRESS_MASK |
                    Gdk::Event::Mask::BUTTON_RELEASE_MASK |
                    Gdk::Event::Mask::KEY_PRESS_MASK |
                    Gdk::Event::Mask::KEY_RELEASE_MASK

    @area.signal_connect(:scroll_event) do |object, event|
        dir = event.direction
        if dir == :up or dir == :left
            zoom_out event.x, event.y
        elsif dir == :down or dir == :right
            zoom_in event.x, event.y
        end
    end

    @area.signal_connect(:draw)                   {|object, cc| redraw }
    @area.signal_connect(:configure_event)        {|object, event| on_configure event}
    @area.signal_connect(:button_press_event)           {|object, event| on_button_press event}
    @area.signal_connect(:button_release_event)         {|object, event| on_button_release event}
    
    @area.can_focus = true
    self.signal_connect(:key_press_event)           {|object, event| on_key_press event}

    self.signal_connect(:drag_drop)             {|widget, context, x, y, time| on_drag_drop context, x, y}

    @scale = 1.0
    @centerX = 0.0
    @centerY = 0.0
    @width = nil
    @height = nil
end

Public Instance Methods

on_button_press(event) click to toggle source
# File lib/etti/ui/label-layout.rb, line 83
def on_button_press event
    @area.grab_focus
    @buttonData = {:x => event.x, :y => event.y,
                   :tempX => event.x, :tempY => event.y,
                   :button => event.button}
end
on_button_release(event) click to toggle source
# File lib/etti/ui/label-layout.rb, line 91
def on_button_release event
    return if @buttonData.nil?

    # left button
    if event.button == 1
        if @buttonData[:x].in(event.x() -5, event.x() +5) and @buttonData[:y].in(event.y() -5, event.y() +5)
            x, y = *view_to_pos(event.x, event.y)
            lastSelected = @selectedElement
            @selectedElement = nil
            type = :none
            # get the type of the element at_pos
            @elements.each do |element|
                if element.at_pos self, x, y
                    if element.is_a? Etti::Element::Data
                        type = :data
                    else
                        raise RuntimeError, 'invalid type ' + element.class.to_s
                    end
                    @selectedElement = element
                    break
                end
            end

            # set the current property editor
            @propertyEditors.each_pair do |key, val|
                if key == type
                    val.show
                else
                    val.hide
                end
            end

            unless type == :none
                @propertyEditors[type].set_selected_element @selectedElement
                @propertyEditors[type].set_from_data
            end
            queue_draw
        end
    end
    @buttonData = nil
end
on_configure(event) click to toggle source
# File lib/etti/ui/label-layout.rb, line 157
def on_configure event
    @width  = event.width
    @height = event.height
    # at the first run zoom to the default label
    zoom_fit if @backBuffer.nil?
    @backBuffer = Cairo::ImageSurface.new Cairo::Format::RGB24, @width, @height
    queue_draw
end
on_drag_drop(context, x, y) click to toggle source
# File lib/etti/ui/label-layout.rb, line 67
def on_drag_drop context, x, y
    type = context.source_widget.dnd_data.type
    data = context.source_widget.dnd_data.data
    cx, cy = *view_to_pos(x, y)
    if type == :data
        idx = @elementDataHeads.index data
        txt = @elementDataData.last[idx]
        @elements << Etti::Element::Data.new(data, txt, cx, cy)
    elsif type == :text
        @elements << Etti::Element::Text.new(data, cx, cy)
    end
    queue_draw
    signal_emit :element_count_changed, @elements.length
end
on_key_press(event) click to toggle source
# File lib/etti/ui/label-layout.rb, line 134
def on_key_press event
    if event.keyval == Gdk::Keyval::GDK_KEY_Delete
        return unless @selectedElement
        @elements.delete_if {|e| e == @selectedElement}
        @selectedElement = nil
        queue_draw

        @propertyEditors.each_pair do |key, val|
            if key == :none
                val.show
            else
                val.hide
            end
        end
    end
end
pos_to_view(x=0.0, y=0.0) click to toggle source
# File lib/etti/ui/label-layout.rb, line 331
def pos_to_view x=0.0, y=0.0
    x1 = (x + @centerX) * @scale + @width / 2.0
    y1 = (y + @centerY) * @scale + @height / 2.0
    [x1, y1]
end
print_labels(cc, page) click to toggle source
queue_draw() click to toggle source
# File lib/etti/ui/label-layout.rb, line 152
def queue_draw
    @area.queue_draw_area 0, 0, @area.allocation.width, @area.allocation.height
end
redraw() click to toggle source
# File lib/etti/ui/label-layout.rb, line 172
def redraw
    # clear the background
    return if @area.window.nil?
    cc = Cairo::Context.new @backBuffer
    cc.set_source_rgb *$colors.bg
    cc.paint

    # draw the shadow under the label
    w, h = *@pageData[:size]
    size = Math.sqrt(60 * @scale)
    sx, sy = *pos_to_view(0, 0)
    cc.shadow_mp sx + size, sy + size, w * @scale - size, h * @scale - size, size, 'rb'

    # draw the label
    cc.set_line_width 2.0
    cc.set_source_rgb 1.0, 1.0, 1.0
    cc.rectangle *pos_to_view(0, 0), w * @scale, h * @scale
    cc.fill_preserve
    cc.set_source_rgb 0.0, 0.0, 0.0
    cc.stroke


    # draw the elements
    @elements.each {|element| element.redraw self, cc}

    # draw the selection
    @selectedElement.draw_selection self unless @selectedElement.nil?

    # draw widget frame
    cc.set_source_rgb 0.0, 0.0, 0.0
    cc.antialias = :none
    cc.line_width = 2.0
    cc.rectangle 0, 0, @area.allocation.width() -1.0, @area.allocation.height() -1.0
    cc.stroke

    # copy backbuffer to the window
    cb = @area.window.create_cairo_context
    cb.set_source @backBuffer
    cb.paint
end
set_element_data(heads, data) click to toggle source
# File lib/etti/ui/label-layout.rb, line 252
def set_element_data heads, data
    @elementDataHeads = heads
    @elementDataData = data
    
    @elements.delete_if do |element|
        !heads.include? element.dataGroup
    end
    unless data.nil?
        @elements.each do |element|
            idx = heads.index element.dataGroup
            element.set_by_name 'text', data.last[idx]
        end
    end
    queue_draw
end
signal_do_element_count_changed(bla;) click to toggle source
# File lib/etti/ui/label-layout.rb, line 7
def signal_do_element_count_changed bla; end
update_page_data(pageData) click to toggle source
# File lib/etti/ui/label-layout.rb, line 167
def update_page_data pageData
    @pageData = pageData
end
view_to_pos(x, y) click to toggle source
# File lib/etti/ui/label-layout.rb, line 338
def view_to_pos x, y
    x1 = (x - @width / 2.0) / @scale - @centerX
    y1 = (y - @height / 2.0) / @scale - @centerY
    [x1, y1]
end
zoom_fit() click to toggle source
# File lib/etti/ui/label-layout.rb, line 297
def zoom_fit
    minX = 2**31
    maxX = - 2**31
    minY = 2**31
    maxY = - 2**31

    if @backBuffer
        @elements.each do |element|
            ext = element.get_extent self
            # TODO use min max methodes
            minX = ext.x if ext.x < minX
            minY = ext.y if ext.y < minY
            maxX = ext.x + ext.width if ext.x + ext.width > maxX
            maxY = ext.y + ext.height if ext.y + ext.height > maxY
        end
    end
    
    # get the label in
    w, h = *@pageData[:size]
    minX = minX.min 0
    minY = minY.min 0
    maxX = maxX.max w
    maxY = maxY.max h
    
    width = maxX - minX
    height = maxY - minY
    @scale = (@width / width).min(@height / height) * 0.95
    @scale = @scale.clamp SCALE_MIN, SCALE_MAX
    @centerX = -(minX + width / 2.0)
    @centerY = -(minY + height / 2.0)
    queue_draw
end
zoom_in(x=nil, y=nil) click to toggle source

x, y is the mouse position, if zoomed with the mouse wheel. with this we can zoom at the mouse position.

# File lib/etti/ui/label-layout.rb, line 271
def zoom_in x=nil, y=nil
    return if @scale >= SCALE_MAX
    @scale = (@scale * 2.0).min SCALE_MAX
    unless x.nil? or y.nil?
        x0 = (@width / 2.0 - x) / @scale
        y0 = (@height / 2.0 - y) / @scale
        @centerX += x0
        @centerY += y0
    end
    queue_draw
end
zoom_out(x=nil, y=nil) click to toggle source
# File lib/etti/ui/label-layout.rb, line 284
def zoom_out x=nil, y=nil
    return if @scale <= SCALE_MIN
    @scale = (@scale / 2.0).max SCALE_MIN
    unless x.nil? or y.nil?
        x0 = (@width / 2.0 - x) / @scale
        y0 = (@height / 2.0 - y) / @scale
        @centerX -= x0 / 2.0
        @centerY -= y0 / 2.0
    end
    queue_draw
end