const int ITEM_SEP = 5
const int FONT_HEIGHT = 15
const int PAD_LEFT = 3
const int PAD_RIGHT = 3
component provides ContextMenu requires ui.Font, os.SystemInfo sysInfo, io.Output out {
Font labelFont
int width = 2
int height = 2
MenuItem menuItems[]
Color borderColor = new Color(180, 180, 200, 255)
Color shadowColor = new Color(180, 180, 180, 255)
Color bgColor = new Color(195, 195, 215, 255)
Color textColor = new Color(0, 0, 0, 255)
Color hlColor = new Color(180, 188, 220, 255)
int hoverIndex = INT_MAX
ContextMenu:ContextMenu()
{
labelFont = new Font(sysInfo.getSystemFont(false), FONT_HEIGHT)
}
void ContextMenu:paint(Canvas c)
{
c.rect(new Rect2D(xPosition+2, yPosition+2, width, height, shadowColor))
c.rect(new Rect2D(xPosition, yPosition, width, height, bgColor))
int ryPos = yPosition
for (int i = 0; i < menuItems.arrayLength; i++)
{
if (i == hoverIndex)
{
c.rect(new Rect2D(xPosition, ryPos, width, FONT_HEIGHT + ITEM_SEP, hlColor))
}
c.text(new Point2D(xPosition+PAD_LEFT, ryPos, textColor), labelFont, menuItems[i].name)
ryPos += FONT_HEIGHT + ITEM_SEP
}
c.rectOutline(new Rect2D(xPosition, yPosition, width, height, borderColor))
}
void ContextMenu:addItem(store MenuItem item)
{
menuItems = new MenuItem[](menuItems, item)
height += FONT_HEIGHT + ITEM_SEP
int textWidth = labelFont.getTextWidth(item.name)
if ((textWidth + PAD_LEFT + PAD_RIGHT) > width)
{
width = textWidth + PAD_LEFT + PAD_RIGHT
}
}
void ContextMenu:remItem(MenuItem item)
{
}
void ContextMenu:setItems(store MenuItem items[])
{
menuItems = items
for (int i = 0; i < items.arrayLength; i++)
{
int textWidth = labelFont.getTextWidth(items[i].name)
if ((textWidth + PAD_LEFT + PAD_RIGHT) > width)
{
width = textWidth + PAD_LEFT + PAD_RIGHT
}
}
height = (FONT_HEIGHT + ITEM_SEP) * items.arrayLength
}
void ContextMenu:setPosition(int x, int y)
{
xPosition = x
yPosition = y
}
void ContextMenu:click(int x, int y, int button)
{
if (button == MouseButtons.BUTTON_LEFT)
{
int ryPos = 0
for (int i = 0; i < menuItems.arrayLength; i++)
{
if (y > ryPos && y < ryPos + FONT_HEIGHT)
{
emitevent menuClick(menuItems[i])
break
}
ryPos += FONT_HEIGHT + ITEM_SEP
}
}
}
void ContextMenu:postRepaint()
{
emitevent repaint()
}
void ContextMenu:setFocus()
{
emitevent requestFocus()
}
void ContextMenu:setDisabled(bool d)
{
disabled = d
postRepaint()
}
Rect ContextMenu:getBounds()
{
return new Rect(xPosition, yPosition, width, height)
}
WH ContextMenu:getPreferredSize()
{
return new WH(width, height)
}
Point ContextMenu:getPosition()
{
return new Point(xPosition, yPosition)
}
void ContextMenu:mouseMove(int x, int y)
{
int ryPos = 0
for (int i = 0; i < menuItems.arrayLength; i++)
{
if (y > ryPos && y < ryPos + FONT_HEIGHT)
{
if (i != hoverIndex)
{
hoverIndex = i
postRepaint()
}
break
}
ryPos += FONT_HEIGHT + ITEM_SEP
}
}
void ContextMenu:mouseOut()
{
hoverIndex = INT_MAX
postRepaint()
}
}