File: //lib64/libreoffice/program/wizards/ui/ImageList.py
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This file incorporates work covered by the following license notice:
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed
# with this work for additional information regarding copyright
# ownership. The ASF licenses this file to you under the Apache
# License, Version 2.0 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.apache.org/licenses/LICENSE-2.0 .
#
import uno
import traceback
from abc import abstractmethod
from threading import RLock
from .PeerConfig import PeerConfig
from .event.CommonListener import OMouseListenerProcAdapter
from ..common.PropertyNames import PropertyNames
from ..common.HelpIds import HelpIds
from ..common.IRenderer import IRenderer
from .event.ListDataListener import ListDataListener
from com.sun.star.awt import Size
def synchronized(lock):
''' Synchronization decorator. '''
def wrap(f):
def newFunction(*args, **kw):
lock.acquire()
try:
return f(*args, **kw)
finally:
lock.release()
return newFunction
return wrap
class ImageList(ListDataListener):
NO_BORDER = 0
BACKGROUND_COLOR = 16777216
HIDE_PAGE = 99
TRANSPARENT = -1
LINE_HEIGHT = 8
IMAGE_PROPS = ("Border", "BackgroundColor",
PropertyNames.PROPERTY_HEIGHT,
PropertyNames.PROPERTY_HELPURL,
PropertyNames.PROPERTY_POSITION_X,
PropertyNames.PROPERTY_POSITION_Y, "ScaleImage",
PropertyNames.PROPERTY_STEP,
PropertyNames.PROPERTY_TABINDEX, "Tabstop",
PropertyNames.PROPERTY_WIDTH)
MOVE_SELECTION = (PropertyNames.PROPERTY_POSITION_X,
PropertyNames.PROPERTY_POSITION_Y,
PropertyNames.PROPERTY_STEP)
lock = RLock()
listModel = None
btnNext = None
btnBack = None
def __init__(self):
self.benabled = True
self.gap = Size(4, 4)
self.cols = 4
self.rows = 3
self.imageSize = Size(20, 20)
self.selectionGap = Size(2, 2)
self.showButtons = True
self.refreshOverNull = True
self.imageTextLines = 1
self.rowSelect = False
self.scaleImages = True
self.name = "il"
self.selected = -1
self.pageStart = 0
self.helpURL = 0
self.renderer = None
self.counterRenderer = self.SimpleCounterRenderer()
self.MOVE_SELECTION_VALS = list(range(3))
self.itemListenerList = None
def onMousePressed(self, event):
self.focus(self.getImageIndexFor(self.selected))
def create(self, dialog):
self.oUnoDialog = dialog
self.dialogModel = dialog.xDialogModel
imageTextHeight = self.imageTextLines * ImageList.LINE_HEIGHT
opeerConfig = PeerConfig(dialog)
self.MOVE_SELECTION_VALS[2] = self.step
imgContainer = dialog.insertImage(
self.name + "lblContainer",
("BackgroundColor", "Border",
PropertyNames.PROPERTY_HEIGHT,
PropertyNames.PROPERTY_POSITION_X,
PropertyNames.PROPERTY_POSITION_Y,
PropertyNames.PROPERTY_STEP,
PropertyNames.PROPERTY_WIDTH),
(ImageList.BACKGROUND_COLOR, 1,
(self.imageSize.Height + self.gap.Height) \
* self.rows + self.gap.Height + imageTextHeight + 1,
self.pos.Width, self.pos.Height, self.step,
(self.imageSize.Width + self.gap.Width) \
* self.cols + self.gap.Width))
opeerConfig.setPeerProperties(imgContainer,"MouseTransparent", True)
if self.rowSelect:
selectionWidth = (self.imageSize.Width + self.gap.Width) \
* self.cols - self.gap.Width + (self.selectionGap.Width * 2)
else:
selectionWidth = self.imageSize.Width + (self.selectionGap.Width * 2)
self.grbxSelectedImage = dialog.insertLabel(
self.name + "_grbxSelected",
("BackgroundColor", "Border",
PropertyNames.PROPERTY_HEIGHT,
PropertyNames.PROPERTY_POSITION_X,
PropertyNames.PROPERTY_POSITION_Y,
PropertyNames.PROPERTY_STEP, "Tabstop",
PropertyNames.PROPERTY_WIDTH),
(ImageList.TRANSPARENT, 1,
self.imageSize.Height + (self.selectionGap.Height * 2),
0, #posx
0, #posy
self.step, True, selectionWidth))
xWindow = self.grbxSelectedImage
xWindow.addMouseListener(OMouseListenerProcAdapter(self.onMousePressed))
pNames1 = (PropertyNames.PROPERTY_HEIGHT,
PropertyNames.PROPERTY_HELPURL,
PropertyNames.PROPERTY_POSITION_X,
PropertyNames.PROPERTY_POSITION_Y,
PropertyNames.PROPERTY_STEP,
PropertyNames.PROPERTY_TABINDEX, "Tabstop",
PropertyNames.PROPERTY_WIDTH)
self.lblImageText = dialog.insertLabel(
self.name + "_imageText", pNames1,
(imageTextHeight, "", self.pos.Width + 1,
self.pos.Height + (self.imageSize.Height + self.gap.Height) \
* self.rows + self.gap.Height, self.step, 0, False,
self.cols * (self.imageSize.Width + self.gap.Width) \
+ self.gap.Width - 2))
if self.showButtons:
ImageList.btnBack = dialog.insertButton(
self.name + "_btnBack", "prevPage", pNames1,
(14, HelpIds.getHelpIdString((self.helpURL + 1)),
self.pos.Width, self.pos.Height + \
(self.imageSize.Height + self.gap.Height) * \
self.rows + self.gap.Height + imageTextHeight + 1,
self.step, self.tabIndex + 1, True, 14), self)
ImageList.btnNext = dialog.insertButton(
self.name + "_btnNext", "nextPage", pNames1,
(14, HelpIds.getHelpIdString((self.helpURL + 1)),
self.pos.Width + (self.imageSize.Width + self.gap.Width) * \
self.cols + self.gap.Width - 14 + 1,
self.pos.Height + (self.imageSize.Height + self.gap.Height) \
* self.rows + self.gap.Height + imageTextHeight + 1,
self.step, self.tabIndex + 2, True, 14), self)
self.lblCounter = dialog.insertLabel(
self.name + "_lblCounter", pNames1,
(ImageList.LINE_HEIGHT, "", self.pos.Width + 14 + 1,int(
self.pos.Height + (self.imageSize.Height + self.gap.Height) \
* self.rows + self.gap.Height + imageTextHeight + \
((14 - ImageList.LINE_HEIGHT) / 2)),
self.step, 0, False, self.cols * \
(self.imageSize.Width + self.gap.Width) + \
self.gap.Width - 2 * 14 - 1))
self.lblCounter.Model.Align = 1
ImageList.btnBack.Model.Label = "<"
ImageList.btnNext.Model.Label = ">"
self.m_aImages = [None] * (self.rows * self.cols)
for r in range(self.rows):
for c in range(self.cols):
self.m_aImages[r * self.cols + c] = self.createImage(dialog, r, c)
self.refreshImages()
self.listModel.addListDataListener(self)
#used for optimization
def createImage(self, dialog, _row, _col):
imageName = self.name + "_image" + str(_row * self.cols + _col)
image = dialog.insertImage(
imageName, ImageList.IMAGE_PROPS,
(ImageList.NO_BORDER,
ImageList.BACKGROUND_COLOR,
self.imageSize.Height,
HelpIds.getHelpIdString(self.helpURL + 1),
self.getImagePosX(_col), self.getImagePosY(_row),
self.scaleImages,
self.step,
self.tabIndex,
False,
self.imageSize.Width))
#COMMENTED
image.addMouseListener(OMouseListenerProcAdapter(self.mousePressed))
image.addKeyListener(None)
return image
def getImagePosX(self, col):
return self.pos.Width + col * \
(self.imageSize.Width + self.gap.Width) + self.gap.Width
def getImagePosY(self, row):
return self.pos.Height + row * \
(self.imageSize.Height + self.gap.Height) + self.gap.Height
def refreshImages(self):
if self.showButtons:
self.refreshCounterText()
self.hideSelection()
if self.refreshOverNull:
i = 0
for i in self.m_aImages:
i.Visible = False
focusable = True
for index, item in enumerate(self.m_aImages):
oResources = self.renderer.getImageUrls(self.getObjectFor(index))
if oResources is not None:
if len(oResources) == 1:
item.Model.ImageURL = oResources[0]
elif len(oResources) == 2:
self.oUnoDialog.getPeerConfiguration().setImageUrl(
item.Model, oResources[0], oResources[1])
item.Model.Tabstop = bool(focusable)
if self.refreshOverNull:
item.Visible = True
focusable = False
self.refreshSelection()
def refreshCounterText(self):
self.lblCounter.Model.Label = self.counterRenderer.render(
self.Counter (self.pageStart + 1, self.pageEnd(),
self.listModel.getSize()))
def pageEnd(self):
i = self.pageStart + self.cols * self.rows
if i > self.listModel.getSize() - 1:
return self.listModel.getSize()
else:
return i
def refreshSelection(self):
if self.selected < self.pageStart or \
self.selected >= (self.pageStart + self.rows * self.cols):
self.hideSelection()
else:
self.moveSelection(self.getImageIndexFor(self.selected))
def hideSelection(self):
self.grbxSelectedImage.Model.Step = ImageList.HIDE_PAGE
self.grbxSelectedImage.Visible = False
'''
Utility field holding list of ItemListeners.
'''
def moveSelection(self, image):
self.grbxSelectedImage.Visible = False
row = int(image / self.cols)
if self.rowSelect:
col = 0
else:
col = image - (row * self.cols)
self.MOVE_SELECTION_VALS[0] = \
int(self.getImagePosX(col) - self.selectionGap.Width)
self.MOVE_SELECTION_VALS[1] = \
int(self.getImagePosY(row) - self.selectionGap.Height)
uno.invoke(self.grbxSelectedImage.Model, "setPropertyValues",
((ImageList.MOVE_SELECTION),
(tuple(self.MOVE_SELECTION_VALS))))
if (self.dialogModel.Step == self.step):
self.grbxSelectedImage.Visible = True
#now focus...
for index,item in enumerate(self.m_aImages):
if index != image:
self.defocus(index)
else:
self.m_aImages[image].Model.Tabstop = True
'''
@param i
@return the Object in the list model corresponding to the given image index
'''
def getObjectFor(self, i):
ii = self.getIndexFor(i)
if self.listModel.getSize() <= ii:
return None
else:
return self.listModel.getElementAt(ii)
'''
@param i
@return the index in the listModel for the given image index.
'''
def getIndexFor(self, i):
return self.pageStart + i
def getImageIndexFor(self, i):
return i - self.pageStart
def intervalAdded(self, event):
if event.getIndex0() <= self.selected:
if event.getIndex1() <= self.selected:
self.selected += event.getIndex1() - event.getIndex0() + 1
if event.getIndex0() < self.pageStart or \
event.getIndex1() < (self.pageStart + self.rows + self.cols):
self.refreshImages()
'''
Registers ItemListener to receive events.
@param listener The listener to register.
'''
@synchronized(lock)
def addItemListener(self, listener):
if self.itemListenerList is None:
self.itemListenerList = []
self.itemListenerList.append(listener)
'''
Removes ItemListener from the list of listeners.
@param listener The listener to remove.
'''
@synchronized(lock)
def removeItemListener(self, listener):
if self.itemListenerList is not None:
self.itemListenerList.remove(listener)
'''
Notifies all registered listeners about the event.
@param event The event to be fired
'''
def fireItemSelected(self):
if self.itemListenerList is None:
return
auxlist = list(self.itemListenerList)
for i in auxlist:
i.itemStateChanged(None)
def getSelected(self):
return self.selected
def setSelected(self, _object):
if (isinstance (_object, int)):
self.setSelected1(_object)
elif (_object is None or _object is ""):
self.setSelected1(-1)
else:
i = 0
while (i < self.listModel.getSize()):
item = self.listModel.getElementAt(i)
if item == _object:
self.setSelected1(i)
return
i += 1
def setSelected1(self, index):
if self.rowSelect and (index >= 0):
index = int(index / self.cols) * self.cols
if self.selected == index:
return
self.selected = index
self.refreshImageText()
self.refreshSelection()
self.fireItemSelected()
def refreshImageText(self):
if self.selected >= 0:
try:
item = self.listModel.getElementAt(self.selected)
except IndexError:
item = None
traceback.print_exc()
else:
item = None
self.lblImageText.Model.Label = " " + self.renderer.render(item)
def nextPage(self):
if self.pageStart < self.listModel.getSize() - self.rows * self.cols:
self.setPageStart(self.pageStart + self.rows * self.cols)
def prevPage(self):
if self.pageStart == 0:
return
i = self.pageStart - self.rows * self.cols
if i < 0:
i = 0
self.setPageStart(i)
def setPageStart(self, i):
if (i == self.pageStart):
return
self.pageStart = i
self.enableButtons()
self.refreshImages()
def enableButtons(self):
self.enable(
ImageList.btnNext,
bool(self.pageStart + self.rows * self.cols < self.listModel.getSize()))
self.enable(ImageList.btnBack, bool(self.pageStart > 0))
def enable(self, control, enable):
control.Model.Enabled = enable
def setBorder(self, control, border):
uno.invoke(control.Model, "setPropertyValues",(("Border"), (enable)))
def getImageFromEvent(self, event):
image = (event).Source
controlName = image.Model.Name
return int(controlName[6 + len(self.name):])
def mousePressed(self, event):
image = self.getImageFromEvent(event)
index = self.getIndexFor(image)
if index < self.listModel.getSize():
self.focus(image)
self.setSelected(index)
def getSelectedObjects(self):
return[self.listModel.getElementAt(self.selected)]
class IImageRenderer(IRenderer):
# @param listItem
# @return two resource ids for an image referenced in the imaglist resourcefile of the
# wizards project; The second one of them is designed to be used for High Contrast Mode.
@abstractmethod
def getImageUrls(self, listItem):
pass
class SimpleCounterRenderer(IRenderer):
def render(self, counter):
return \
"" + (counter).start + ".." + (counter).end + "/" + (counter).max
class Counter(object):
def __init__(self, start_, end_, max_):
self.start = start_
self.end = end_
self.max = max_
def getSelectedObject(self):
if self.selected >= 0:
try:
return self.listModel.getElementAt(self.selected)
except IndexError:
traceback.print_exc()
return None
def showSelected(self):
oldPageStart = self.pageStart
if self.selected != -1:
self.pageStart = \
int((self.selected / len(self.m_aImages)) * len(self.m_aImages))
if oldPageStart != self.pageStart:
self.enableButtons()
self.refreshImages()
def keyPressed(self, ke):
image = self.getImageFromEvent(ke)
r = image / self.cols
c = image - (r * self.cols)
d = self.getKeyMove(ke, r, c)
newImage = image + d
if newImage == image:
return
if self.isFocusable(newImage):
self.changeFocus(image, newImage)
def isFocusable(self, image):
return (image >= 0) and \
(self.getIndexFor(image) < self.listModel.getSize())
def changeFocus(self, oldFocusImage, newFocusImage):
self.focus(newFocusImage)
self.defocus(oldFocusImage)
def select(self, ke):
self.setSelected(self.getIndexFor(self.getImageFromEvent(ke)))
def focus(self, image):
self.m_aImages[image].Model.Tabstop = True
xWindow = self.m_aImages[image]
xWindow.setFocus()
def defocus(self, image):
self.m_aImages[image].Model.Tabstop = False
'''jump to the given item (display the screen
that contains the given item).
@param i
'''
def display(self, i):
isAux = (self.cols * self.rows)
ps = (self.listModel.getSize() / isAux) * isAux
self.setPageStart(ps)
def setenabled(self, b):
i = 0
while i < len(self.m_aImages):
UnoDialog2.setEnabled(self.m_aImages[i], b)
i += 1
UnoDialog2.setEnabled(self.grbxSelectedImage, b)
UnoDialog2.setEnabled(self.lblImageText, b)
if self.showButtons:
UnoDialog2.setEnabled(ImageList.btnBack, b)
UnoDialog2.setEnabled(ImageList.btnNext, b)
UnoDialog2.setEnabled(self.lblCounter, b)
self.benabled = b