PopupMenuHaiku.cpp [plain text]
#include "config.h"
#include "PopupMenu.h"
#include "FrameView.h"
#include "NotImplemented.h"
#include <Application.h>
#include <Handler.h>
#include <MenuItem.h>
#include <Message.h>
#include <PopUpMenu.h>
#include <String.h>
#include <Window.h>
#include <support/Autolock.h>
#include <support/Locker.h>
namespace WebCore {
static const uint32 kPopupResult = 'pmrs';
static const uint32 kPopupHidden = 'pmhd';
class PopupMenuHandler : public BHandler {
public:
PopupMenuHandler(PopupMenuClient* popupClient)
: m_popupClient(popupClient)
{
}
virtual void MessageReceived(BMessage* message)
{
switch (message->what) {
case kPopupResult: {
int32 index = 0;
message->FindInt32("index", &index);
m_popupClient->valueChanged(index);
break;
}
case kPopupHidden:
m_popupClient->popupDidHide();
break;
default:
BHandler::MessageReceived(message);
}
}
private:
PopupMenuClient* m_popupClient;
};
class PopupMenuHaiku : public BPopUpMenu {
public:
PopupMenuHaiku(PopupMenuClient* popupClient)
: BPopUpMenu("WebCore Popup", true, false)
, m_popupClient(popupClient)
, m_Handler(popupClient)
{
if (be_app->Lock()) {
be_app->AddHandler(&m_Handler);
be_app->Unlock();
}
SetAsyncAutoDestruct(false);
}
virtual ~PopupMenuHaiku()
{
if (be_app->Lock()) {
be_app->RemoveHandler(&m_Handler);
be_app->Unlock();
}
}
void show(const IntRect& rect, FrameView* view, int index)
{
for (int32 i = CountItems() - 1; i >= 0; i--)
delete RemoveItem(i);
int itemCount = m_popupClient->listSize();
for (int i = 0; i < itemCount; i++) {
if (m_popupClient->itemIsSeparator(i))
AddSeparatorItem();
else {
BString label(m_popupClient->itemText(i));
BMessage* message = new BMessage(kPopupResult);
message->AddInt32("index", i);
BMenuItem* item = new BMenuItem(label.String(), message);
AddItem(item);
item->SetTarget(BMessenger(&m_Handler));
item->SetEnabled(m_popupClient->itemIsEnabled(i));
item->SetMarked(i == index);
}
}
DoLayout();
BRect screenRect(view->contentsToScreen(rect));
screenRect.OffsetBy(2, 2);
if (BMenuItem* item = ItemAt(index))
screenRect.OffsetBy(0, -item->Frame().top);
BRect openRect = Bounds().OffsetToSelf(screenRect.LeftTop());
Go(screenRect.LeftTop(), true, true, openRect, true);
}
void hide()
{
if (!IsHidden())
Hide();
}
private:
virtual void Hide()
{
BPopUpMenu::Hide();
be_app->PostMessage(kPopupHidden, &m_Handler);
}
PopupMenuClient* m_popupClient;
PopupMenuHandler m_Handler;
};
PopupMenu::PopupMenu(PopupMenuClient* client)
: m_popupClient(client)
, m_menu(new PopupMenuHaiku(client))
{
}
PopupMenu::~PopupMenu()
{
delete m_menu;
}
void PopupMenu::show(const IntRect& rect, FrameView* view, int index)
{
m_menu->show(rect, view, index);
}
void PopupMenu::hide()
{
m_menu->hide();
}
void PopupMenu::updateFromElement()
{
client()->setTextFromItem(m_popupClient->selectedIndex());
}
bool PopupMenu::itemWritingDirectionIsNatural()
{
return false;
}
}