ruler.py :  » GUI » Sketch » skencil-0.6.17 » Sketch » UI » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » GUI » Sketch 
Sketch » skencil 0.6.17 » Sketch » UI » ruler.py
# Sketch - A Python-based interactive drawing program
# Copyright (C) 1997, 1998, 1999, 2001, 2003 by Bernhard Herzog
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

from math import floor,ceil,hypot
from string import atoi
from types import TupleType
import operator

import pax

from Sketch import config,const,GuideLine,Point
from Sketch.warn import warn,USER
from Sketch.const import CHANGED

from tkext import PyWidget

from Sketch.Lib import units

HORIZONTAL = 0
VERTICAL = 1

tick_lengths = (8, 5, 3, 2)

# (base_unit_factor, (subdiv1, subdiv2,...))
tick_config = {'in': (1.0, (2, 2, 2, 2)),
               'cm': (1.0, (2, 5)),
               'mm': (10.0, (2, 5)),
               'pt': (100.0, (2, 5, 2, 5)),
               #'pt': (72.0, (2, 3, 12)),
               }

class Ruler(PyWidget):

    def __init__(self, master=None, orient = HORIZONTAL, canvas = None, **kw):
  apply(PyWidget.__init__, (self, master), kw)
  self.orient = orient
        self.canvas = canvas
  self.gcs_initialized = 0
  self.gc = None
        self.positions = None
  self.SetRange(0.0, 1.0, force = 1)
        if orient == VERTICAL:
            self.text_type = config.preferences.ruler_text_type
        else:
            self.text_type = 'horizontal'
  font = None
  fontname = config.preferences.ruler_font
  try:
      font = self.tkwin.LoadQueryFont(fontname)
  except:
      # NLS
      warn(USER, 'Could not load font %s for ruler. using defaults.',
     `fontname`)
            font = self.tkwin.LoadQueryFont('fixed')
  self.font = font
        
        font = None
        if self.text_type == 'rotated':
            fontname = config.preferences.ruler_font_rotated
            try:
                font = self.tkwin.LoadQueryFont(fontname)
            except:
                # NLS
                warn(USER, 'Could not load font %s for ruler. using defaults.',
                     `fontname`)
        self.rotated_font = font
        if not self.rotated_font and self.text_type == 'rotated':
            self.text_type = 'horizontal'
            
  border_width = self.option_get('borderWidth', 'BorderWidth')
  if border_width:
      self.border_width = atoi(border_width)
  else:
      self.border_width = 0

        height = self.font.ascent + self.font.descent \
                 + self.border_width + tick_lengths[0]
  if orient == HORIZONTAL:
      self['height'] = height
  else:
            if self.text_type == 'rotated':
                self['width'] = height
            elif self.text_type == 'vertical':
                self['width'] = self.font.TextWidth('0') + self.border_width \
                        + tick_lengths[0]
            else: # horizontal
                width = self.font.TextWidth('000') + self.border_width \
                        + tick_lengths[0]
                self['width'] = width

  self.bind('<ButtonPress>', self.ButtonPressEvent)
  self.bind('<ButtonRelease>', self.ButtonReleaseEvent)
  self.bind('<Motion>', self.PointerMotionEvent)
        self.button_down = 0
        self.forward_motion = 0

        config.preferences.Subscribe(CHANGED, self.preference_changed)

    def destroy(self):
  PyWidget.destroy(self)
        self.canvas = None

    def MapMethod(self):
  if not self.gcs_initialized:
      self.init_gcs()
      self.gcs_initialized = 1

    def init_gcs(self):
  cmap = self.tkwin.colormap()
  foreground = cmap.AllocColor(0, 0, 0)[0]
  attrs = {'foreground': foreground, 'line_width':0}
        if not self.rotated_font:
            if self.font:
                attrs['font'] = self.font
        else:
            attrs['font'] = self.rotated_font
  self.gc = self.tkwin.GetGC(attrs)
        if self.font is None:
            self.font = self.gc.font

    def ResizedMethod(self, width, height):
  self.SetRange(self.start, self.pixel_per_pt, force = 1)

    def SetRange(self, start, pixel_per_pt, force = 0):
  if not force and start==self.start and pixel_per_pt==self.pixel_per_pt:
      return
  self.start = start
  self.pixel_per_pt = pixel_per_pt
        self.positions = None
  self.UpdateWhenIdle()

    def preference_changed(self, pref, value):
        if pref == 'default_unit':
            self.positions = None # force recomputation
            self.UpdateWhenIdle()

    def get_positions(self):
        if self.positions is not None:
            return self.positions, self.texts

        min_text_step = config.preferences.ruler_min_text_step
        max_text_step = config.preferences.ruler_max_text_step
        min_tick_step = config.preferences.ruler_min_tick_step
  if self.orient == HORIZONTAL:
      length = self.tkwin.width
            origin = self.start
  else:
      length = self.tkwin.height
            origin = self.start - length / self.pixel_per_pt
        unit_name = config.preferences.default_unit
        pt_per_unit = units.unit_dict[unit_name]
        units_per_pixel = 1.0 / (pt_per_unit * self.pixel_per_pt)
        factor, subdivisions = tick_config[unit_name]
        subdivisions = (1,) + subdivisions

        factor = factor * pt_per_unit
        start_pos = floor(origin / factor) * factor
        main_tick_step = factor * self.pixel_per_pt
        num_ticks = floor(length / main_tick_step) + 2

        if main_tick_step < min_tick_step:
            tick_step = ceil(min_tick_step / main_tick_step) * main_tick_step
            subdivisions = (1,)
            ticks = 1
        else:
            tick_step = main_tick_step
            ticks = 1
            for depth in range(len(subdivisions)):
                tick_step = tick_step / subdivisions[depth]
                if tick_step < min_tick_step:
                    tick_step = tick_step * subdivisions[depth]
                    depth = depth - 1
                    break
                ticks = ticks * subdivisions[depth]
            subdivisions = subdivisions[:depth + 1]
        
        positions = range(int(num_ticks * ticks))
        positions = map(operator.mul, [tick_step] * len(positions), positions)
        positions = map(operator.add, positions,
                        [(start_pos - origin) * self.pixel_per_pt]
                        * len(positions))

        stride = ticks
        marks = [None] * len(positions)
        for depth in range(len(subdivisions)):
            stride = stride / subdivisions[depth]
            if depth >= len(tick_lengths):
                height = tick_lengths[-1]
            else:
                height = tick_lengths[depth]
            for i in range(0, len(positions), stride):
                if marks[i] is None:
                    marks[i] = (height, int(round(positions[i])))

        texts = []
        if main_tick_step < min_text_step:
            stride = int(ceil(min_text_step / main_tick_step))
            start_index = stride - (floor(origin / factor) % stride)
            start_index = int(start_index * ticks)
            stride = stride * ticks
        else:
            start_index = 0
            stride = ticks
            step = main_tick_step
            for div in subdivisions:
                step = step / div
                if step < min_text_step:
                    break
                stride = stride / div
                if step < max_text_step:
                    break

        for i in range(start_index, len(positions), stride):
            pos = positions[i] * units_per_pixel + origin / pt_per_unit
            pos = round(pos, 3)
            if pos == 0.0:
                # avoid '-0' strings
                pos = 0.0
            texts.append(("%g" % pos, marks[i][-1]))
        self.positions = marks
        self.texts = texts

        return self.positions, self.texts
        

    def RedrawMethod(self, region = None):
  pixmap = self.tkwin.CreatePixmap()
  width = self.tkwin.width
  height = self.tkwin.height
  bd = self.border_width
  self.gc.SetDrawable(pixmap)
  self.tkborder.Fill3DRectangle(pixmap, 0, 0, width, height,
              bd, pax.TK_RELIEF_RAISED);
  if self.orient == HORIZONTAL:
      self.draw_ruler_horizontal()
  else:
      self.draw_ruler_vertical()
  self.gc.SetDrawable(self.tkwin)
  pixmap.CopyArea(self.tkwin, self.gc, 0, 0, width, height, 0, 0)


    def draw_ruler_horizontal(self):
  darkgc = self.tkborder.BorderGC(pax.TK_3D_DARK_GC)
  darkgc.SetDrawable(self.gc.drawable)
  lightgc = self.tkborder.BorderGC(pax.TK_3D_LIGHT_GC)
  lightgc.SetDrawable(self.gc.drawable)
  DrawString = self.gc.DrawString
  DrawDarkLine = darkgc.DrawLine
  DrawLightLine = lightgc.DrawLine
  TextWidth = self.font.TextWidth
  descent = self.font.descent
  height = self.tkwin.height
        
        ticks, texts = self.get_positions()
        for h, pos in ticks:
      DrawDarkLine(pos, height, pos, height - h)
      pos = pos + 1
      DrawLightLine(pos, height, pos, height - h)

        y = height - tick_lengths[0] - descent
        for text, pos in texts:
            if text[0] != '-':
                tw = TextWidth(text)
            else:
                tw = TextWidth(text[1:])
                pos = pos - TextWidth('-')
            DrawString(pos - tw / 2, y, text)

    def draw_ruler_vertical(self):
  darkgc = self.tkborder.BorderGC(pax.TK_3D_DARK_GC)
  darkgc.SetDrawable(self.gc.drawable)
  lightgc = self.tkborder.BorderGC(pax.TK_3D_LIGHT_GC)
  lightgc.SetDrawable(self.gc.drawable)
  DrawString = self.gc.DrawString
  DrawDarkLine = darkgc.DrawLine
  DrawLightLine = lightgc.DrawLine
        descent = self.font.descent
  height = self.tkwin.height
        width = self.tkwin.width
  font_height = self.font.ascent + self.font.descent

        ticks, texts = self.get_positions()
        for h, pos in ticks:
            pos = height - pos
      DrawDarkLine(width - h, pos, width, pos)
      pos = pos + 1
      DrawLightLine(width - h, pos, width, pos)

        if self.text_type == 'rotated':
            TextWidth = self.font.TextWidth
            x = width - self.font.descent - tick_lengths[0]
            for text, pos in texts:
                pos = height - pos
                if text[0] != '-':
                    tw = TextWidth(text)
                else:
                    tw = TextWidth(text[1:])
                    pos = pos + TextWidth('-')
                y = pos + tw / 2
                for c in text:
                    DrawString(x, y, c)
                    y = y - TextWidth(c)
        elif self.text_type == 'vertical':
            x = width - self.font.TextWidth('0') - tick_lengths[0]
            for text, pos in texts:
                pos = height - pos
                #print `text`
                y = pos + self.font.ascent - (len(text) * font_height) / 2
                for c in text:
                    DrawString(x, y, c)
                    y = y + font_height
        else: # horizontal
            TextWidth = self.font.TextWidth 
            dx = width - tick_lengths[0]
            dy = self.font.ascent - font_height / 2
            for text, pos in texts:
                pos = height - pos + dy
                #print `text`
                DrawString(dx - TextWidth(text), pos, text)

    def ButtonPressEvent(self, event):
        if event.num == const.Button1:
            self.button_down = 1
            self.pressevent = event
        
    def ButtonReleaseEvent(self, event):
        if event.num == const.Button1:
            self.button_down = 0

    def PointerMotionEvent(self, event):
        if self.button_down:
            if self.canvas is not None:
                press = self.pressevent
                if hypot(press.x - event.x, press.y - event.y) > 3:
                    guide = GuideLine(Point(0, 0), self.orient == HORIZONTAL)
                    self.canvas.PlaceObject(guide)
                    press.x = press.x_root - self.canvas.winfo_rootx()
                    press.y = press.y_root - self.canvas.winfo_rooty()
                    self.canvas.ButtonPressEvent(press)
                    self.canvas.grab_set()
                    self.button_down = 0

    def SetCanvas(self, canvas):
        self.canvas = canvas
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.