Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2014-02-08 19:33:26 (GMT)
committer Walter Bender <walter@sugarlabs.org>2014-02-08 19:33:26 (GMT)
commitb8ea5b4e550eb115415a1f4544605d5c649e2496 (patch)
tree5fb0214cba9f04a0f87e5a2c7aad5b0adc2e86f6
parentc55b60922025842357a22fc34bb6a241dc94d413 (diff)
make PaletteView class to simplify palette management
-rw-r--r--TurtleArt/tapaletteview.py423
-rw-r--r--TurtleArt/tawindow.py381
2 files changed, 465 insertions, 339 deletions
diff --git a/TurtleArt/tapaletteview.py b/TurtleArt/tapaletteview.py
new file mode 100644
index 0000000..213ee17
--- /dev/null
+++ b/TurtleArt/tapaletteview.py
@@ -0,0 +1,423 @@
+# -*- coding: utf-8 -*-
+#Copyright (c) 2014, Walter Bender
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+_SKIN_IMAGE = 1
+_MARGIN = 5
+_BUTTON_SIZE = 32
+
+from tautils import find_group, debug_output
+from tablock import Block
+from tapalette import (palette_names, palette_blocks, hidden_proto_blocks,
+ block_styles)
+from taconstants import (PALETTE_SCALE, ICON_SIZE, PYTHON_SKIN, XO1,
+ HORIZONTAL_PALETTE, PALETTE_WIDTH, PALETTE_HEIGHT,
+ CATEGORY_LAYER, TOP_LAYER, PROTO_LAYER)
+from tasprite_factory import SVG, svg_str_to_pixbuf
+from sprites import Sprite
+
+
+def _width_and_height(blk):
+ ''' What are the width and height of a stack? '''
+ minx = 10000
+ miny = 10000
+ maxx = -10000
+ maxy = -10000
+ for gblk in find_group(blk):
+ (x, y) = gblk.spr.get_xy()
+ w, h = gblk.spr.get_dimensions()
+ if x < minx:
+ minx = x
+ if y < miny:
+ miny = y
+ if x + w > maxx:
+ maxx = x + w
+ if y + h > maxy:
+ maxy = y + h
+ return(maxx - minx, maxy - miny)
+
+
+class PaletteView():
+ ''' Palette View class abstraction '''
+
+ def __init__(self, turtle_window, n):
+ '''
+ This class handles the display of block palettes
+ '''
+ self.blocks = []
+ self.backgrounds = [None, None]
+
+ self._turtle_window = turtle_window
+ self._palette_index = n
+ self._visible = False
+ self._populated = False
+
+ if not n < len(palette_names):
+ # Shouldn't happen, but hey...
+ debug_output('palette index %d is out of range' % n,
+ self._turtle_window.running_sugar)
+ self._name = 'undefined'
+ else:
+ self._name = palette_names[n]
+
+ def create(self, regenerate=True, show=False):
+ if not self._name == 'undefined':
+ # Create proto blocks for each palette entry
+ self._create_proto_blocks()
+
+ save_selected = self._turtle_window.selected_palette
+ self.layout_palette(regenerate=regenerate,
+ show=(show or
+ save_selected == self._palette_index))
+
+ def show(self):
+ ''' Show palette background and proto blocks. If needed, display
+ shift button. '''
+ orientation = self._turtle_window.orientation
+ if self.backgrounds[orientation] is not None:
+ self.backgrounds[orientation].set_layer(CATEGORY_LAYER)
+
+ for blk in self.blocks:
+ if blk.get_visibility():
+ blk.spr.set_layer(PROTO_LAYER)
+ else:
+ blk.spr.hide()
+
+ self.display_palette_shift_buttons()
+
+ def hide(self):
+ ''' Hide the palette. '''
+ for background in self.backgrounds:
+ if background is not None:
+ background.hide()
+
+ for blk in self.blocks:
+ blk.spr.hide()
+
+ self._hide_palette_shift_buttons()
+
+ if self._trash_palette():
+ for blk in self._turtle_window.trash_stack:
+ for gblk in find_group(blk):
+ gblk.spr.hide()
+
+ def move(self, x, y):
+ ''' Move the palette. '''
+ buttons = self._turtle_window.palette_button
+
+ for blk in self.blocks:
+ blk.spr.move((x + blk.spr.save_xy[0], y + blk.spr.save_xy[1]))
+
+ for button in buttons:
+ button.move((x + button.save_xy[0], y + button.save_xy[1]))
+
+ for spr in self.backgrounds:
+ if spr is not None:
+ spr.move((x + spr.save_xy[0], y + spr.save_xy[1]))
+
+ if self._trash_palette():
+ for blk in self._turtle_window.trash_stack:
+ for gblk in find_group(blk):
+ gblk.spr.move((x + gblk.spr.save_xy[0],
+ y + gblk.spr.save_xy[1]))
+
+ def shift(self):
+ ''' Shift blocks on the palette. '''
+ buttons = self._turtle_window.palette_button
+ orientation = self._turtle_window.orientation
+
+ x, y = self.backgrounds[orientation].get_xy()
+ w, h = self.backgrounds[orientation].get_dimensions()
+ bx, by = self.blocks[0].spr.get_xy()
+ if orientation == 0:
+ width = self._turtle_window.width
+
+ if bx != _BUTTON_SIZE:
+ dx = w - width
+ else:
+ dx = width - w
+ dy = 0
+ else:
+ height = self._turtle_window.height
+ offset = self._turtle_window.toolbar_offset
+
+ dx = 0
+ if by != offset + _BUTTON_SIZE + _MARGIN:
+ dy = h - height + ICON_SIZE
+ else:
+ dy = height - h - ICON_SIZE
+
+ for blk in self.blocks:
+ if blk.get_visibility():
+ blk.spr.move_relative((dx, dy))
+
+ buttons[orientation].set_layer(TOP_LAYER)
+ if dx < 0 or dy < 0:
+ buttons[orientation + 5].set_layer(TOP_LAYER)
+ buttons[orientation + 3].hide()
+ else:
+ buttons[orientation + 5].hide()
+ buttons[orientation + 3].set_layer(TOP_LAYER)
+
+ def _create_proto_blocks(self):
+ '''
+ Create the proto blocks that will populate this palette.
+ Reload the palette, but reuse the existing blocks.
+ If a block doesn't exist, add it.
+ '''
+ for blk in self.blocks:
+ blk.spr.hide()
+
+ preexisting_blocks = self.blocks[:]
+ self.blocks = []
+ for name in palette_blocks[self._palette_index]:
+ # Did we already create this block?
+ preexisting_block = False
+ for blk in preexisting_blocks:
+ if blk.name == name:
+ self.blocks.append(blk)
+ preexisting_block = True
+ break
+
+ # If not, create it now.
+ if not preexisting_block:
+ self.blocks.append(Block(self._turtle_window.block_list,
+ self._turtle_window.sprite_list,
+ name, 0, 0, 'proto', [],
+ PALETTE_SCALE))
+ if name in hidden_proto_blocks:
+ self.blocks[-1].set_visibility(False)
+ else:
+ self.blocks[-1].spr.set_layer(PROTO_LAYER)
+ self.blocks[-1].unhighlight()
+ self.blocks[-1].resize()
+
+ # Some proto blocks get a skin.
+ if name in block_styles['box-style-media']:
+ self._proto_skin(name + 'small', self.blocks[-1].spr)
+ elif name in PYTHON_SKIN:
+ self._proto_skin('pythonsmall', self.blocks[-1].spr)
+ elif len(self.blocks[-1].spr.labels) > 0:
+ self.blocks[-1].refresh()
+
+ def _proto_skin(self, name, spr):
+ ''' Utility for creating proto block skins '''
+ x, y = self._turtle_window._calc_image_offset(name, spr)
+ spr.set_image(self._turtle_window.media_shapes[name], _SKIN_IMAGE,
+ x, y)
+
+ def _float_palette(self, spr):
+ ''' We sometimes let the palette move with the canvas. '''
+ if self._turtle_window.running_sugar and \
+ not self._turtle_window.hw in [XO1]:
+ spr.move_relative(
+ (self._turtle_window.activity.hadj_value,
+ self._turtle_window.activity.vadj_value))
+
+ def _trash_palette(self):
+ return 'trash' in palette_names and \
+ self._palette_index == palette_names.index('trash')
+
+ def layout_palette(self, regenerate=False, show=True):
+ ''' Layout prototypes in a palette. '''
+
+ offset = self._turtle_window.toolbar_offset
+ buttons = self._turtle_window.palette_button
+ orientation = self._turtle_window.orientation
+ w = PALETTE_WIDTH
+ h = PALETTE_HEIGHT
+
+ if orientation == HORIZONTAL_PALETTE:
+ x, y, max_w = self._horizontal_layout(
+ _BUTTON_SIZE, offset + _MARGIN, self.blocks)
+ if self._trash_palette():
+ blocks = [] # self.blocks[:]
+ for blk in self._turtle_window.trash_stack:
+ blocks.append(blk)
+ x, y, max_w = self._horizontal_layout(x + max_w, y, blocks)
+ w = x + max_w + _BUTTON_SIZE + _MARGIN
+ if show:
+ buttons[2].move((w - _BUTTON_SIZE, offset))
+ buttons[4].move((_BUTTON_SIZE, offset))
+ buttons[6].move((_BUTTON_SIZE, offset))
+ else:
+ x, y, max_h = self._vertical_layout(
+ _MARGIN, offset + _BUTTON_SIZE + _MARGIN, self.blocks)
+ if self._trash_palette():
+ blocks = [] # self.blocks[:]
+ for blk in self._turtle_window.trash_stack:
+ blocks.append(blk)
+ x, y, max_h = self._vertical_layout(x, y + max_h, blocks)
+ h = y + max_h + _BUTTON_SIZE + _MARGIN - offset
+ if show:
+ buttons[2].move((PALETTE_WIDTH - _BUTTON_SIZE, offset))
+ buttons[3].move((0, offset + _BUTTON_SIZE))
+ buttons[5].move((0, offset + _BUTTON_SIZE))
+
+ self._make_background(0, offset, w, h, regenerate)
+
+ if show:
+ for blk in self.blocks:
+ if blk.get_visibility():
+ blk.spr.set_layer(PROTO_LAYER)
+ else:
+ blk.spr.hide()
+
+ buttons[2].save_xy = buttons[2].get_xy()
+ self._float_palette(buttons[2])
+ self.backgrounds[orientation].set_layer(CATEGORY_LAYER)
+ self.display_palette_shift_buttons()
+
+ if self._trash_palette():
+ for blk in self._turtle_window.trash_stack:
+ for gblk in find_group(blk):
+ gblk.spr.set_layer(PROTO_LAYER)
+
+ svg = SVG()
+ self.backgrounds[orientation].set_shape(
+ svg_str_to_pixbuf(svg.palette(w, h)))
+
+ def _make_background(self, x, y, w, h, regenerate=False):
+ ''' Make the background sprite for the palette. '''
+ orientation = self._turtle_window.orientation
+
+ if regenerate and not self.backgrounds[orientation] is None:
+ self.backgrounds[orientation].hide()
+ self.backgrounds[orientation] = None
+
+ if self.backgrounds[orientation] is None:
+ svg = SVG()
+ self.backgrounds[orientation] = \
+ Sprite(self._turtle_window.sprite_list, x, y,
+ svg_str_to_pixbuf(svg.palette(w, h)))
+ self.backgrounds[orientation].save_xy = (x, y)
+
+ self._float_palette(self.backgrounds[orientation])
+
+ if orientation == 0 and w > self._turtle_window.width:
+ self.backgrounds[orientation].type = \
+ 'category-shift-horizontal'
+ elif orientation == 1 and \
+ h > self._turtle_window.height - ICON_SIZE:
+ self.backgrounds[orientation].type = \
+ 'category-shift-vertical'
+ else:
+ self.backgrounds[orientation].type = 'category'
+
+ '''
+ if self._trash_palette():
+ svg = SVG()
+ self.backgrounds[orientation].set_shape(
+ svg_str_to_pixbuf(svg.palette(w, h)))
+ '''
+
+ def _horizontal_layout(self, x, y, blocks):
+ ''' Position prototypes in a horizontal palette. '''
+ offset = self._turtle_window.toolbar_offset
+ max_w = 0
+
+ for blk in blocks:
+ if not blk.get_visibility():
+ continue
+
+ w, h = _width_and_height(blk)
+ if y + h > PALETTE_HEIGHT + offset:
+ x += int(max_w + 3)
+ y = offset + 3
+ max_w = 0
+
+ (bx, by) = blk.spr.get_xy()
+ dx = x - bx
+ dy = y - by
+ for g in find_group(blk):
+ g.spr.move_relative((int(dx), int(dy)))
+ g.spr.save_xy = g.spr.get_xy()
+ self._float_palette(g.spr)
+ y += int(h + 3)
+ if w > max_w:
+ max_w = w
+
+ return x, y, max_w
+
+ def _vertical_layout(self, x, y, blocks):
+ ''' Position prototypes in a vertical palette. '''
+ row = []
+ row_w = 0
+ max_h = 0
+
+ for blk in blocks:
+ if not blk.get_visibility():
+ continue
+
+ w, h = _width_and_height(blk)
+ if x + w > PALETTE_WIDTH:
+ # Recenter row.
+ dx = int((PALETTE_WIDTH - row_w) / 2)
+ for r in row:
+ for g in find_group(r):
+ g.spr.move_relative((dx, 0))
+ g.spr.save_xy = (g.spr.save_xy[0] + dx,
+ g.spr.save_xy[1])
+ row = []
+ row_w = 0
+ x = 4
+ y += int(max_h + 3)
+ max_h = 0
+
+ row.append(blk)
+ row_w += (4 + w)
+
+ (bx, by) = blk.spr.get_xy()
+ dx = int(x - bx)
+ dy = int(y - by)
+ for g in find_group(blk):
+ g.spr.move_relative((dx, dy))
+ g.spr.save_xy = g.spr.get_xy()
+ self._float_palette(g.spr)
+
+ x += int(w + 4)
+ if h > max_h:
+ max_h = h
+
+ # Recenter last row.
+ dx = int((PALETTE_WIDTH - row_w) / 2)
+ for r in row:
+ for g in find_group(r):
+ g.spr.move_relative((dx, 0))
+ g.spr.save_xy = (g.spr.save_xy[0] + dx, g.spr.save_xy[1])
+
+ return x, y, max_h
+
+ def _hide_palette_shift_buttons(self):
+ buttons = self._turtle_window.palette_button
+ for i in range(4):
+ buttons[i + 3].hide()
+
+ def display_palette_shift_buttons(self):
+ ''' Palettes too wide (or tall) for the screen get a shift button. '''
+ self._hide_palette_shift_buttons()
+
+ buttons = self._turtle_window.palette_button
+ orientation = self._turtle_window.orientation
+
+ if self.backgrounds[orientation].type == 'category-shift-horizontal':
+ buttons[3].set_layer(CATEGORY_LAYER)
+ elif self.backgrounds[orientation].type == 'category-shift-vertical':
+ buttons[4].set_layer(CATEGORY_LAYER)
diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py
index f92d9d7..dcc4b18 100644
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -52,20 +52,19 @@ from taconstants import (HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE,
MEDIA_SHAPES, STATUS_SHAPES, OVERLAY_SHAPES,
TOOLBAR_SHAPES, TAB_LAYER, RETURN, OVERLAY_LAYER,
CATEGORY_LAYER, BLOCKS_WITH_SKIN, ICON_SIZE,
- PALETTE_SCALE, PALETTE_WIDTH, SKIN_PATHS, MACROS,
+ PALETTE_WIDTH, SKIN_PATHS, MACROS, Color, KEY_DICT,
TOP_LAYER, BLOCK_LAYER, OLD_NAMES, DEFAULT_TURTLE,
TURTLE_LAYER, EXPANDABLE, NO_IMPORT, TEMPLATES,
PYTHON_SKIN, PALETTE_HEIGHT, STATUS_LAYER, OLD_DOCK,
EXPANDABLE_ARGS, XO1, XO15, XO175, XO30, XO4, TITLEXY,
CONTENT_ARGS, CONSTANTS, EXPAND_SKIN, PROTO_LAYER,
- EXPANDABLE_FLOW, SUFFIX, TMP_SVG_PATH, TMP_ODP_PATH,
- Color, KEY_DICT)
+ EXPANDABLE_FLOW, SUFFIX, TMP_SVG_PATH, TMP_ODP_PATH)
from tapalette import (palette_names, palette_blocks, expandable_blocks,
block_names, content_blocks, default_values,
special_names, block_styles, help_strings,
- hidden_proto_blocks, string_or_number_args,
- make_palette, palette_name_to_index,
- palette_init_on_start, palette_i18n_names)
+ string_or_number_args, make_palette,
+ palette_name_to_index, palette_init_on_start,
+ palette_i18n_names)
from talogo import (LogoCode, logoerror)
from tacanvas import TurtleGraphics
from tablock import (Blocks, Block, Media, media_blocks_dictionary)
@@ -83,6 +82,7 @@ from tautils import (magnitude, get_load_name, get_save_name, data_from_file,
increment_name, get_screen_dpi)
from tasprite_factory import (SVG, svg_str_to_pixbuf, svg_from_file)
from tapalette import block_primitives
+from tapaletteview import PaletteView
from sprites import (Sprites, Sprite)
if _GST_AVAILABLE:
@@ -243,9 +243,8 @@ class TurtleArtWindow():
self.status_spr = None
self.status_shapes = {}
self.toolbar_spr = None
- self.palette_sprs = []
- self.palettes = []
self.palette_button = []
+ self.palette_views = []
self.trash_stack = []
self.selected_palette = None
self.previous_palette = None
@@ -907,7 +906,7 @@ class TurtleArtWindow():
self.show_toolbar_palette(n)
self.palette_button[self.orientation].set_layer(TAB_LAYER)
self.palette_button[2].set_layer(TAB_LAYER)
- self._display_palette_shift_button(n)
+ self.palette_views[n].display_palette_shift_buttons()
if not self.running_sugar or not self.activity.has_toolbarbox:
self.toolbar_spr.set_layer(CATEGORY_LAYER)
self.palette = True
@@ -924,26 +923,12 @@ class TurtleArtWindow():
def move_palettes(self, x, y):
''' Move the palettes. '''
- for p in self.palettes:
- for blk in p:
- blk.spr.move((x + blk.spr.save_xy[0], y + blk.spr.save_xy[1]))
- for spr in self.palette_button:
- spr.move((x + spr.save_xy[0], y + spr.save_xy[1]))
- for p in self.palette_sprs:
- if p[0] is not None:
- p[0].move((x + p[0].save_xy[0], y + p[0].save_xy[1]))
- if p[1] is not None:
- p[1].move((x + p[1].save_xy[0], y + p[1].save_xy[1]))
+ for palette in self.palette_views:
+ palette.move(x, y)
self.status_spr.move((x + self.status_spr.save_xy[0],
y + self.status_spr.save_xy[1]))
- # To do: set save_xy for blocks in Trash
- for blk in self.trash_stack:
- for gblk in find_group(blk):
- gblk.spr.move((x + gblk.spr.save_xy[0],
- y + gblk.spr.save_xy[1]))
-
def hideblocks(self):
''' Callback from 'hide blocks' block '''
if not self.interactive_mode:
@@ -985,34 +970,6 @@ class TurtleArtWindow():
int(blocks[0].font_size[0] * pango.SCALE * self.entry_scale))
self._text_entry.modify_font(font_desc)
- def _shift_toolbar_palette(self, n):
- ''' Shift blocks on specified palette '''
- x, y = self.palette_sprs[n][self.orientation].get_xy()
- w, h = self.palette_sprs[n][self.orientation].get_dimensions()
- bx, by = self.palettes[n][0].spr.get_xy()
- if self.orientation == 0:
- if bx != _BUTTON_SIZE:
- dx = w - self.width
- else:
- dx = self.width - w
- dy = 0
- else:
- dx = 0
- if by != self.toolbar_offset + _BUTTON_SIZE + _MARGIN:
- dy = h - self.height + ICON_SIZE
- else:
- dy = self.height - h - ICON_SIZE
- for blk in self.palettes[n]:
- if blk.get_visibility():
- blk.spr.move_relative((dx, dy))
- self.palette_button[self.orientation].set_layer(TOP_LAYER)
- if dx < 0 or dy < 0:
- self.palette_button[self.orientation + 5].set_layer(TOP_LAYER)
- self.palette_button[self.orientation + 3].hide()
- else:
- self.palette_button[self.orientation + 5].hide()
- self.palette_button[self.orientation + 3].set_layer(TOP_LAYER)
-
def show_toolbar_palette(self, n, init_only=False, regenerate=False,
show=True):
''' Show the toolbar palettes, creating them on init_only '''
@@ -1024,7 +981,7 @@ class TurtleArtWindow():
self._create_the_selectors()
# Create the empty palettes that we'll then populate with prototypes.
- if self.palette_sprs == []:
+ if self.palette_views == []:
self._create_the_empty_palettes()
# At initialization of the program, we don't actually populate
@@ -1052,34 +1009,12 @@ class TurtleArtWindow():
self.selectors[i].set_layer(TAB_LAYER)
# Show the palette with the current orientation.
- if self.palette_sprs[n][self.orientation] is not None:
- self.palette_sprs[n][self.orientation].set_layer(
+ if self.palette_views[n].backgrounds[self.orientation] is not None:
+ self.palette_views[n].backgrounds[self.orientation].set_layer(
CATEGORY_LAYER)
- self._display_palette_shift_button(n)
-
- # Create 'proto' blocks for each palette entry
- self._create_proto_blocks(n)
+ self.palette_views[n].display_palette_shift_buttons()
- if show or save_selected == n:
- self._layout_palette(n, regenerate=regenerate)
- else:
- self._layout_palette(n, regenerate=regenerate, show=False)
- for blk in self.palettes[n]:
- if blk.get_visibility():
- if hasattr(blk.spr, 'set_layer'):
- blk.spr.set_layer(PROTO_LAYER)
- else:
- debug_output('WARNING: block sprite is None' % (blk.name),
- self.running_sugar)
- else:
- blk.spr.hide()
- if 'trash' in palette_names and \
- n == palette_names.index('trash'):
- for blk in self.trash_stack:
- # Deprecated
- for gblk in find_group(blk):
- if gblk.status != 'collapsed':
- gblk.spr.set_layer(TAB_LAYER)
+ self.palette_views[n].create(regenerate=regenerate, show=show)
if not show:
if not save_selected == n:
@@ -1092,7 +1027,7 @@ class TurtleArtWindow():
if (not self.running_sugar or not self.activity.has_toolbarbox) and \
self.selectors == []:
return
- if self.palette_sprs == []:
+ if self.palette_views == []:
return
save_selected = self.selected_palette
@@ -1100,37 +1035,14 @@ class TurtleArtWindow():
self.selected_palette = n
self.previous_palette = self.selected_palette
- if save_selected == n:
- self._layout_palette(n, regenerate=True)
- else:
- self._layout_palette(n, regenerate=True, show=False)
-
- for blk in self.palettes[n]:
- if blk.get_visibility():
- if hasattr(blk.spr, 'set_layer'):
- blk.spr.set_layer(PROTO_LAYER)
- else:
- debug_output('WARNING: block sprite is None' % (blk.name),
- self.running_sugar)
- else:
- blk.spr.hide()
+ self.palette_views[n].layout_palette(regenerate=True,
+ show=(save_selected == n))
if not save_selected == n:
self._hide_previous_palette(palette=n)
self.selected_palette = save_selected
self.previous_palette = save_previous
- def _display_palette_shift_button(self, n):
- ''' Palettes too wide (or tall) for the screen get a shift button '''
- for i in range(4):
- self.palette_button[i + 3].hide()
- if self.palette_sprs[n][self.orientation].type == \
- 'category-shift-horizontal':
- self.palette_button[3].set_layer(CATEGORY_LAYER)
- elif self.palette_sprs[n][self.orientation].type == \
- 'category-shift-vertical':
- self.palette_button[4].set_layer(CATEGORY_LAYER)
-
def _create_the_selectors(self):
''' Create the palette selector buttons: only when running
old-style Sugar toolbars or from GNOME '''
@@ -1185,13 +1097,8 @@ class TurtleArtWindow():
def _create_the_empty_palettes(self):
''' Create the empty palettes to be populated by prototype blocks. '''
- if len(self.palettes) == 0:
- for i in range(len(palette_blocks)):
- self.palettes.append([])
-
- # Create empty palette backgrounds
- for i in palette_names:
- self.palette_sprs.append([None, None])
+ for i in range(len(palette_names)):
+ self.palette_views.append(PaletteView(self, i))
# Create the palette orientation button
self.palette_button.append(
@@ -1268,57 +1175,6 @@ class TurtleArtWindow():
self.palette_button[3 + i].type = 'palette'
self.palette_button[3 + i].hide()
- def _create_proto_blocks(self, n):
- ''' Create the protoblocks that will populate a palette. '''
- # Reload the palette, but reuse the existing blocks
- # If a block doesn't exist, add it
-
- if not n < len(self.palettes):
- debug_output(
- '_create_proto_blocks: palette index %d is out of range' %
- (n), self.running_sugar)
- return
-
- for blk in self.palettes[n]:
- blk.spr.hide()
- old_blocks = self.palettes[n][:]
- self.palettes[n] = []
- for name in palette_blocks[n]:
- found_block = False
- for oblk in old_blocks:
- if oblk.name == name:
- self.palettes[n].append(oblk)
- found_block = True
- break
- if not found_block:
- self.palettes[n].append(
- Block(self.block_list, self.sprite_list, name, 0, 0,
- 'proto', [], PALETTE_SCALE))
- if name in hidden_proto_blocks:
- self.palettes[n][-1].set_visibility(False)
- else:
- if hasattr(self.palettes[n][-1].spr, 'set_layer'):
- self.palettes[n][-1].spr.set_layer(PROTO_LAYER)
- self.palettes[n][-1].unhighlight()
- self.palettes[n][-1].resize()
- else:
- debug_output('WARNING: block sprite is None' %
- (self.palettes[n][-1].name),
- self.running_sugar)
-
- # Some proto blocks get a skin.
- if name in block_styles['box-style-media']:
- self._proto_skin(name + 'small', n, -1)
- elif name[:8] == 'template': # Deprecated
- self._proto_skin(name[8:], n, -1)
- elif name[:7] == 'picture': # Deprecated
- self._proto_skin(name[7:], n, -1)
- elif name in PYTHON_SKIN:
- self._proto_skin('pythonsmall', n, -1)
- if len(self.palettes[n][-1].spr.labels) > 0:
- self.palettes[n][-1].refresh()
- return
-
def _hide_toolbar_palette(self):
''' Hide the toolbar palettes '''
self._hide_previous_palette()
@@ -1337,15 +1193,7 @@ class TurtleArtWindow():
palette = self.previous_palette
# Hide previously selected palette
if palette is not None:
- if not palette < len(self.palettes):
- debug_output(
- '_hide_previous_palette: index %d is out of range' %
- (palette), self.running_sugar)
- return
- for proto in self.palettes[palette]:
- proto.spr.hide()
- if self.palette_sprs[palette][self.orientation] is not None:
- self.palette_sprs[palette][self.orientation].hide()
+ self.palette_views[palette].hide()
if not self.running_sugar or not self.activity.has_toolbarbox:
self.selectors[palette].set_shape(
self.selector_shapes[palette][0])
@@ -1353,155 +1201,6 @@ class TurtleArtWindow():
and not self.activity.has_toolbarbox:
self.activity.palette_buttons[palette].set_icon(
palette_names[palette] + 'off')
- if 'trash' in palette_names and \
- palette == palette_names.index('trash'):
- for blk in self.trash_stack:
- for gblk in find_group(blk):
- gblk.spr.hide()
-
- def _horizontal_layout(self, x, y, blocks):
- ''' Position prototypes in a horizontal palette. '''
- max_w = 0
- for blk in blocks:
- if not blk.get_visibility():
- continue
- w, h = self._width_and_height(blk)
- if y + h > PALETTE_HEIGHT + self.toolbar_offset:
- x += int(max_w + 3)
- y = self.toolbar_offset + 3
- max_w = 0
- (bx, by) = blk.spr.get_xy()
- dx = x - bx
- dy = y - by
- for g in find_group(blk):
- g.spr.move_relative((int(dx), int(dy)))
- g.spr.save_xy = g.spr.get_xy()
- if self.running_sugar and not self.hw in [XO1]:
- g.spr.move_relative((self.activity.hadj_value,
- self.activity.vadj_value))
- y += int(h + 3)
- if w > max_w:
- max_w = w
- return x, y, max_w
-
- def _vertical_layout(self, x, y, blocks):
- ''' Position prototypes in a vertical palette. '''
- row = []
- row_w = 0
- max_h = 0
- for blk in blocks:
- if not blk.get_visibility():
- continue
- w, h = self._width_and_height(blk)
- if x + w > PALETTE_WIDTH:
- # Recenter row.
- dx = int((PALETTE_WIDTH - row_w) / 2)
- for r in row:
- for g in find_group(r):
- g.spr.move_relative((dx, 0))
- g.spr.save_xy = (g.spr.save_xy[0] + dx,
- g.spr.save_xy[1])
- row = []
- row_w = 0
- x = 4
- y += int(max_h + 3)
- max_h = 0
- row.append(blk)
- row_w += (4 + w)
- (bx, by) = blk.spr.get_xy()
- dx = int(x - bx)
- dy = int(y - by)
- for g in find_group(blk):
- g.spr.move_relative((dx, dy))
- g.spr.save_xy = g.spr.get_xy()
- if self.running_sugar and not self.hw in [XO1]:
- g.spr.move_relative((self.activity.hadj_value,
- self.activity.vadj_value))
- x += int(w + 4)
- if h > max_h:
- max_h = h
- # Recenter last row.
- dx = int((PALETTE_WIDTH - row_w) / 2)
- for r in row:
- for g in find_group(r):
- g.spr.move_relative((dx, 0))
- g.spr.save_xy = (g.spr.save_xy[0] + dx, g.spr.save_xy[1])
- return x, y, max_h
-
- def _layout_palette(self, n, regenerate=False, show=True):
- ''' Layout prototypes in a palette. '''
- if n is not None:
- if self.orientation == HORIZONTAL_PALETTE:
- x, y = _BUTTON_SIZE, self.toolbar_offset + _MARGIN
- x, y, max_w = self._horizontal_layout(x, y, self.palettes[n])
- if 'trash' in palette_names and \
- n == palette_names.index('trash'):
- x, y, max_w = self._horizontal_layout(x + max_w, y,
- self.trash_stack)
- w = x + max_w + _BUTTON_SIZE + _MARGIN
- self._make_palette_spr(n, 0, self.toolbar_offset,
- w, PALETTE_HEIGHT, regenerate)
- if show:
- self.palette_button[2].move(
- (w - _BUTTON_SIZE, self.toolbar_offset))
- self.palette_button[4].move(
- (_BUTTON_SIZE, self.toolbar_offset))
- self.palette_button[6].move(
- (_BUTTON_SIZE, self.toolbar_offset))
- else:
- x, y = _MARGIN, self.toolbar_offset + _BUTTON_SIZE + _MARGIN
- x, y, max_h = self._vertical_layout(x, y, self.palettes[n])
- if 'trash' in palette_names and \
- n == palette_names.index('trash'):
- x, y, max_h = self._vertical_layout(x, y + max_h,
- self.trash_stack)
- h = y + max_h + _BUTTON_SIZE + _MARGIN - self.toolbar_offset
- self._make_palette_spr(n, 0, self.toolbar_offset,
- PALETTE_WIDTH, h, regenerate)
- if show:
- self.palette_button[2].move((PALETTE_WIDTH - _BUTTON_SIZE,
- self.toolbar_offset))
- self.palette_button[3].move(
- (0, self.toolbar_offset + _BUTTON_SIZE))
- self.palette_button[5].move(
- (0, self.toolbar_offset + _BUTTON_SIZE))
- if show:
- self.palette_button[2].save_xy = \
- self.palette_button[2].get_xy()
- if self.running_sugar and not self.hw in [XO1]:
- self.palette_button[2].move_relative(
- (self.activity.hadj_value, self.activity.vadj_value))
- self.palette_sprs[n][self.orientation].set_layer(
- CATEGORY_LAYER)
- self._display_palette_shift_button(n)
-
- def _make_palette_spr(self, n, x, y, w, h, regenerate=False):
- ''' Make the background for the palette. '''
- if regenerate and not self.palette_sprs[n][self.orientation] is None:
- self.palette_sprs[n][self.orientation].hide()
- self.palette_sprs[n][self.orientation] = None
- if self.palette_sprs[n][self.orientation] is None:
- svg = SVG()
- self.palette_sprs[n][self.orientation] = \
- Sprite(self.sprite_list, x, y, svg_str_to_pixbuf(
- svg.palette(w, h)))
- self.palette_sprs[n][self.orientation].save_xy = (x, y)
- if self.running_sugar and not self.hw in [XO1]:
- self.palette_sprs[n][self.orientation].move_relative(
- (self.activity.hadj_value, self.activity.vadj_value))
- if self.orientation == 0 and w > self.width:
- self.palette_sprs[n][self.orientation].type = \
- 'category-shift-horizontal'
- elif self.orientation == 1 and h > self.height - ICON_SIZE:
- self.palette_sprs[n][self.orientation].type = \
- 'category-shift-vertical'
- else:
- self.palette_sprs[n][self.orientation].type = 'category'
- if 'trash' in palette_names and \
- n == palette_names.index('trash'):
- svg = SVG()
- self.palette_sprs[n][self.orientation].set_shape(
- svg_str_to_pixbuf(svg.palette(w, h)))
def _buttonpress_cb(self, win, event):
''' Button press '''
@@ -1864,10 +1563,10 @@ before making changes to your program'))
return
i = palette_names.index('myblocks')
palette_blocks[i].remove(blk.name)
- for pblk in self.palettes[i]:
+ for pblk in self.palette_views[i].blocks:
if pblk.name == blk.name:
pblk.spr.hide()
- self.palettes[i].remove(pblk)
+ self.palette_views[i].blocks.remove(pblk)
break
self.show_toolbar_palette(i, regenerate=True)
@@ -1917,7 +1616,7 @@ before making changes to your program'))
palette_names[i] + 'on')
self.show_palette(i)
elif spr.name == _('shift'):
- self._shift_toolbar_palette(self.selected_palette)
+ self.palette_views[self.selected_palette].shift()
else:
self.set_orientation(1 - self.orientation)
elif spr.type == 'toolbar':
@@ -1928,10 +1627,11 @@ before making changes to your program'))
self.orientation = orientation
self.palette_button[self.orientation].set_layer(TAB_LAYER)
self.palette_button[1 - self.orientation].hide()
- spr = self.palette_sprs[self.selected_palette][1 - self.orientation]
+ o = 1 - self.orientation
+ spr = self.palette_views[self.selected_palette].backgrounds[o]
if spr is not None:
spr.hide()
- self._layout_palette(self.selected_palette)
+ self.palette_views[self.selected_palette].layout_palette()
self.show_palette(self.selected_palette)
def _update_action_names(self, name):
@@ -2022,7 +1722,7 @@ before making changes to your program'))
block_names[new] = name
i = palette_name_to_index(palette)
- for blk in self.palettes[i]:
+ for blk in self.palette_views[i].blocks:
if blk.name == old:
blk.name = new
blk.spr.labels[label] = name
@@ -2174,10 +1874,10 @@ before making changes to your program'))
i = palette_name_to_index('blocks')
if name in palette_blocks[i]:
palette_blocks[i].remove(name)
- for blk in self.palettes[i]:
+ for blk in self.palette_views[i].blocks:
if blk.name == name:
blk.spr.hide()
- self.palettes[i].remove(blk)
+ self.palette_views[i].blocks.remove(blk)
self.show_toolbar_palette(i, regenerate=True)
if name in block_styles[style]:
block_styles[style].remove(name)
@@ -2254,10 +1954,11 @@ before making changes to your program'))
def _in_the_trash(self, x, y):
''' Is x, y over a palette? '''
- if self.selected_palette is not None and \
- self.palette_sprs[self.selected_palette][self.orientation]\
- .hit((x, y)):
- return True
+ n = self.selected_palette
+ if n is not None:
+ spr = self.palette_views[n].backgrounds[self.orientation]
+ if spr.hit((x, y)):
+ return True
return False
def _block_pressed(self, x, y, blk):
@@ -3730,7 +3431,7 @@ before making changes to your program'))
print 'selected palette is None'
return True
else:
- p = self.palettes[self.selected_palette]
+ p = self.palette_views[self.selected_palette].blocks
i = 0
if self._highlighted_blk is not None:
self._highlighted_blk.unhighlight()
@@ -4725,7 +4426,7 @@ before making changes to your program'))
if '.odp' not in name:
name = name + '.odp'
if name is not None:
- res = subprocess.check_output(
+ subprocess.check_output(
['cp', TMP_ODP_PATH, os.path.join(datapath, name)])
@@ -4952,8 +4653,10 @@ before making changes to your program'))
def _proto_skin(self, name, n, i):
''' Utility for calculating proto skin images '''
- x, y = self._calc_image_offset(name, self.palettes[n][i].spr)
- self.palettes[n][i].spr.set_image(self.media_shapes[name], 1, x, y)
+ x, y = self._calc_image_offset(name,
+ self.palette_views[n].blocks[i].spr)
+ self.palette_views[n].blocks[i].spr.set_image(
+ self.media_shapes[name], 1, x, y)
def _block_skin(self, name, blk):
''' Some blocks get a skin '''
@@ -4989,7 +4692,7 @@ before making changes to your program'))
if isinstance(label, unicode):
label = label.encode('utf-8')
i = palette_name_to_index(palette)
- for blk in self.palettes[i]:
+ for blk in self.palette_views[i].blocks:
blk_label = blk.spr.labels[0]
if isinstance(blk.name, unicode):
blk.name = blk.name.encode('utf-8')