/* Clementine Window Manager
Copyright 2002 Dave Berton <db@mosey.org>
based on aewm Copyright 1998-2001 Decklin Foster <decklin@red-bean.com>
This program is free software; see LICENSE for details. */
#include "menu.h"
#include "client.h"
#include "windowsystem.h"
#include "painter.h"
#include <assert.h>
Menu::Menu( WindowSystem* windowsystem,
std::vector< Client* > clients,
int x, int y )
: ws(windowsystem),
entries( clients ),
popup(0)
{
assert(ws);
assert(entries.size());
popup = ws->createMenu();
assert( popup );
/* set menu dimensions */
int w = 100;
std::vector< Client* >::const_iterator it;
for ( it = entries.begin(); it != entries.end(); ++it ) {
std::string label = (*it)->name();
int tw = ws->painter()->textWidth( label );
if ( tw > w )
w = tw;
}
width = w;
item_height = ws->painter()->fontAscent() +
ws->painter()->fontDescent() +
ws->pad();
/* Arrange for centre of first menu item to be under pointer. */
start_x = x - width / 2;
start_y = y - item_height / 2;
// db more adjust for edge of screen
if (start_x < 0)
start_x = 0;
if (start_x + width > ws->displayWidth() )
start_x = ws->displayWidth() - width;
if (start_y < 0)
start_y = 0;
x -= start_x;
y -= start_y;
currentItem = item( x, y );
ws->moveResize( popup, start_x, start_y,
width, (entries.size()) * item_height );
ws->mapRaised( popup );
}
Menu::~Menu()
{
if ( popup )
ws->destroy( popup );
}
int Menu::item(int x, int y)
{
if ( x < 0 || x > (int)width ||
y < 0 || y >= (int)(entries.size()*item_height) )
return -1;
return y / item_height;
}
void Menu::expose()
{
drawLabels();
}
void Menu::pointerMotion( int x, int y )
{
int old = currentItem;
x -= start_x;
y -= start_y;
currentItem = item(x, y);
if ( currentItem == old )
return;
/* erase old */
if ( old > -1 && old < (int)entries.size() ) {
drawLabel( old, entries[old]->name() );
}
/* draw new */
if ( currentItem > -1 && currentItem < (int)entries.size() ) {
drawLabel( currentItem, entries[currentItem]->name() );
}
}
void Menu::drawLabels()
{
ws->grabServer();
ws->painter()->setTitlebarBackground( popup, true,
width, item_height*entries.size() );
ws->painter()->clear( popup );
std::vector< Client* >::const_iterator it;
for ( it = entries.begin(); it != entries.end(); ++it ) {
std::string label = (*it)->name();
int entryNum = it - entries.begin();
drawLabel( entryNum, label );
}
ws->ungrabServer();
ws->sync();
}
void Menu::drawLabel( int num, std::string l )
{
int tx = (width - ws->painter()->textWidth( l )) / 2 + ws->pad();
int ty = num * item_height + ws->painter()->fontAscent() + 1;
ws->painter()->drawString( popup, num == currentItem, tx, ty, l );
}
syntax highlighted by Code2HTML, v. 0.9.1