mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-12-14 12:09:36 +00:00
Menu work, move VOS queue interface
This commit is contained in:
@@ -1,7 +1,60 @@
|
||||
#include "MenuManager.h"
|
||||
#include "PLBigEndian.h"
|
||||
#include "DisplayDeviceManager.h"
|
||||
#include "FontFamily.h"
|
||||
#include "FontManager.h"
|
||||
#include "HostDisplayDriver.h"
|
||||
#include "HostFont.h"
|
||||
#include "IGpDisplayDriver.h"
|
||||
#include "MemoryManager.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "SimpleGraphic.h"
|
||||
#include "PLBigEndian.h"
|
||||
#include "PLCore.h"
|
||||
#include "PLPasStr.h"
|
||||
#include "PLResources.h"
|
||||
#include "PLQDOffscreen.h"
|
||||
#include "RenderedFont.h"
|
||||
#include "QDGraf.h"
|
||||
#include "QDManager.h"
|
||||
#include "QDPixMap.h"
|
||||
#include "RGBAColor.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
const PortabilityLayer::RGBAColor gs_barTopLeftCornerGraphicPixels[] =
|
||||
{
|
||||
{ 0, 0, 0, 255 }, { 0, 0, 0, 255 }, { 0, 0, 0, 255 }, { 85, 85, 85, 255 }, { 170, 170, 170, 255 },
|
||||
{ 0, 0, 0, 255 }, { 0, 0, 0, 255 }, { 85, 85, 85, 255 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 },
|
||||
{ 0, 0, 0, 255 }, { 85, 85, 85, 255 }, { 255, 255, 255, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 },
|
||||
{ 85, 85, 85, 255 }, { 255, 255, 255, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 },
|
||||
{ 170, 170, 170, 255 }, { 255, 255, 255, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 },
|
||||
};
|
||||
|
||||
const PortabilityLayer::RGBAColor gs_barTopRightCornerGraphicPixels[] =
|
||||
{
|
||||
{ 170, 170, 170, 255 }, { 85, 85, 85, 255 }, { 0, 0, 0, 255 }, { 0, 0, 0, 255 }, { 0, 0, 0, 255 },
|
||||
{ 255, 255, 255, 255 }, { 255, 255, 255, 255 }, { 85, 85, 85, 255 }, { 0, 0, 0, 255 }, { 0, 0, 0, 255 },
|
||||
{ 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 255, 255, 255, 255 }, { 85, 85, 85, 255 }, { 0, 0, 0, 255 },
|
||||
{ 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 255, 255, 255, 255 }, { 85, 85, 85, 255 },
|
||||
{ 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 221, 221, 221, 255 }, { 255, 255, 255, 255 }, { 85, 85, 85, 255 },
|
||||
};
|
||||
|
||||
const PortabilityLayer::RGBAColor gs_barBrightColor = { 255, 255, 255, 255 };
|
||||
const PortabilityLayer::RGBAColor gs_barMidColor = { 221, 221, 221, 255 };
|
||||
const PortabilityLayer::RGBAColor gs_barDarkColor = { 102, 102, 102, 255 };
|
||||
const PortabilityLayer::RGBAColor gs_barBottomEdgeColor = { 0, 0, 0, 255 };
|
||||
const PortabilityLayer::RGBAColor gs_barNormalTextColor = { 0, 0, 0, 255 };
|
||||
|
||||
const PortabilityLayer::RGBAColor gs_barHighlightBrightColor = { 153, 153, 255, 255 };
|
||||
const PortabilityLayer::RGBAColor gs_barHighlightMidColor = { 102, 102, 204, 255 };
|
||||
const PortabilityLayer::RGBAColor gs_barHighlightDarkColor = { 51, 51, 102, 255 };
|
||||
|
||||
PortabilityLayer::SimpleGraphicInstanceRGBA<5, 5> gs_barTopLeftCornerGraphic(gs_barTopLeftCornerGraphicPixels);
|
||||
PortabilityLayer::SimpleGraphicInstanceRGBA<5, 5> gs_barTopRightCornerGraphic(gs_barTopRightCornerGraphicPixels);
|
||||
}
|
||||
|
||||
struct MenuItem
|
||||
{
|
||||
@@ -21,13 +74,20 @@ struct Menu
|
||||
uint16_t height;
|
||||
uint16_t commandID;
|
||||
bool enabled;
|
||||
bool isIcon;
|
||||
|
||||
PortabilityLayer::MMHandleBlock *stringBlobHandle;
|
||||
|
||||
Menu **prevMenu;
|
||||
Menu **nextMenu;
|
||||
|
||||
// Refreshed on layout
|
||||
size_t cumulativeOffset;
|
||||
unsigned int menuIndex;
|
||||
|
||||
size_t numMenuItems;
|
||||
|
||||
// This must be the last item
|
||||
MenuItem menuItems[1];
|
||||
};
|
||||
|
||||
@@ -39,6 +99,9 @@ namespace PortabilityLayer
|
||||
MenuManagerImpl();
|
||||
~MenuManagerImpl();
|
||||
|
||||
virtual void Init() override;
|
||||
virtual void Shutdown() override;
|
||||
|
||||
Menu **DeserializeMenu(const void *resData) const override;
|
||||
Menu **GetMenuByID(int id) const override;
|
||||
void InsertMenuBefore(Menu **insertingMenu, Menu **existingMenu) override;
|
||||
@@ -49,18 +112,46 @@ namespace PortabilityLayer
|
||||
void SetItemEnabled(Menu **menu, unsigned int index, bool enabled) override;
|
||||
void SetItemChecked(Menu **menu, unsigned int index, bool checked) override;
|
||||
|
||||
void DrawMenuBar() override;
|
||||
|
||||
void RenderFrame(IGpDisplayDriver *displayDriver) override;
|
||||
|
||||
static MenuManagerImpl *GetInstance();
|
||||
|
||||
private:
|
||||
void RefreshMenuLayout();
|
||||
|
||||
static const unsigned int kIconResID = 128;
|
||||
static const unsigned int kMenuFontSize = 12;
|
||||
static const unsigned int kMenuBarIconYOffset = 2;
|
||||
static const unsigned int kMenuBarTextYOffset = 14;
|
||||
static const unsigned int kMenuBarHeight = 20;
|
||||
static const unsigned int kMenuBarItemPadding = 6;
|
||||
static const unsigned int kMenuBarInitialPadding = 16;
|
||||
static const int kMenuFontFlags = PortabilityLayer::FontFamilyFlag_Bold;
|
||||
|
||||
CGraf *m_menuBarGraf;
|
||||
|
||||
Menu **m_firstMenu;
|
||||
Menu **m_lastMenu;
|
||||
bool m_haveMenuLayout;
|
||||
bool m_haveIcon;
|
||||
|
||||
uint8_t m_iconColors[16 * 16];
|
||||
uint8_t m_iconMask[32];
|
||||
|
||||
SimpleGraphic *m_iconGraphic;
|
||||
|
||||
static MenuManagerImpl ms_instance;
|
||||
};
|
||||
|
||||
MenuManagerImpl::MenuManagerImpl()
|
||||
: m_firstMenu(nullptr)
|
||||
: m_menuBarGraf(nullptr)
|
||||
, m_firstMenu(nullptr)
|
||||
, m_lastMenu(nullptr)
|
||||
, m_haveMenuLayout(false)
|
||||
, m_haveIcon(false)
|
||||
, m_iconGraphic(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -68,6 +159,26 @@ namespace PortabilityLayer
|
||||
{
|
||||
}
|
||||
|
||||
void MenuManagerImpl::Init()
|
||||
{
|
||||
}
|
||||
|
||||
void MenuManagerImpl::Shutdown()
|
||||
{
|
||||
PortabilityLayer::QDManager *qdManager = PortabilityLayer::QDManager::GetInstance();
|
||||
|
||||
if (m_menuBarGraf)
|
||||
qdManager->DisposeGWorld(m_menuBarGraf);
|
||||
|
||||
if (m_iconGraphic)
|
||||
{
|
||||
m_iconGraphic->~SimpleGraphic();
|
||||
free(m_iconGraphic);
|
||||
}
|
||||
|
||||
// GP TODO: Dispose of menus properly
|
||||
}
|
||||
|
||||
Menu **MenuManagerImpl::DeserializeMenu(const void *resData) const
|
||||
{
|
||||
PortabilityLayer::MemoryManager *mm = PortabilityLayer::MemoryManager::GetInstance();
|
||||
@@ -122,6 +233,9 @@ namespace PortabilityLayer
|
||||
menu->height = header.height;
|
||||
menu->commandID = header.commandID;
|
||||
menu->enabled = ((enableFlags & 1) != 0);
|
||||
menu->menuIndex = 0;
|
||||
menu->cumulativeOffset = 0;
|
||||
menu->isIcon = false;
|
||||
|
||||
uint8_t *stringDataStart = static_cast<uint8_t*>(stringData->m_contents);
|
||||
uint8_t *stringDest = stringDataStart;
|
||||
@@ -172,6 +286,8 @@ namespace PortabilityLayer
|
||||
|
||||
void MenuManagerImpl::InsertMenuBefore(Menu **insertingMenu, Menu **existingMenu)
|
||||
{
|
||||
m_haveMenuLayout = false;
|
||||
|
||||
Menu *insertingMenuPtr = *insertingMenu;
|
||||
Menu *existingMenuPtr = *existingMenu;
|
||||
|
||||
@@ -188,6 +304,8 @@ namespace PortabilityLayer
|
||||
|
||||
void MenuManagerImpl::InsertMenuAfter(Menu **insertingMenu, Menu **existingMenu)
|
||||
{
|
||||
m_haveMenuLayout = false;
|
||||
|
||||
Menu *insertingMenuPtr = *insertingMenu;
|
||||
Menu *existingMenuPtr = *existingMenu;
|
||||
|
||||
@@ -204,6 +322,8 @@ namespace PortabilityLayer
|
||||
|
||||
void MenuManagerImpl::InsertMenuAtEnd(Menu **insertingMenu)
|
||||
{
|
||||
m_haveMenuLayout = false;
|
||||
|
||||
if (m_firstMenu == nullptr)
|
||||
{
|
||||
m_firstMenu = m_lastMenu = insertingMenu;
|
||||
@@ -217,6 +337,8 @@ namespace PortabilityLayer
|
||||
|
||||
void MenuManagerImpl::InsertMenuAtBeginning(Menu **insertingMenu)
|
||||
{
|
||||
m_haveMenuLayout = false;
|
||||
|
||||
if (m_firstMenu == nullptr)
|
||||
{
|
||||
m_firstMenu = m_lastMenu = insertingMenu;
|
||||
@@ -255,6 +377,228 @@ namespace PortabilityLayer
|
||||
menu->menuItems[index].checked = checked;
|
||||
}
|
||||
|
||||
void MenuManagerImpl::DrawMenuBar()
|
||||
{
|
||||
if (!m_haveIcon)
|
||||
{
|
||||
ResourceManager *resManager = ResourceManager::GetInstance();
|
||||
|
||||
Handle icsHandle = GetResource('ics#', kIconResID);
|
||||
Handle ics8Handle = GetResource('ics8', kIconResID);
|
||||
|
||||
if (icsHandle && ics8Handle)
|
||||
{
|
||||
typedef SimpleGraphicInstanceStandardPalette<16, 16> GraphicType_t;
|
||||
|
||||
void *storage = static_cast<GraphicType_t*>(malloc(sizeof(GraphicType_t)));
|
||||
if (storage)
|
||||
{
|
||||
memcpy(m_iconMask, static_cast<const uint8_t*>(*icsHandle) + 32, 32);
|
||||
memcpy(m_iconColors, static_cast<const uint8_t*>(*ics8Handle), 16 * 16);
|
||||
|
||||
GraphicType_t *graphic = new (storage) GraphicType_t(m_iconColors);
|
||||
|
||||
m_iconGraphic = graphic;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (icsHandle)
|
||||
ReleaseResource(icsHandle);
|
||||
|
||||
if (ics8Handle)
|
||||
ReleaseResource(ics8Handle);
|
||||
|
||||
m_haveIcon = true;
|
||||
}
|
||||
|
||||
unsigned int width;
|
||||
GpPixelFormat_t pixelFormat;
|
||||
PortabilityLayer::HostDisplayDriver::GetInstance()->GetDisplayResolution(&width, nullptr, &pixelFormat);
|
||||
|
||||
PortabilityLayer::QDManager *qdManager = PortabilityLayer::QDManager::GetInstance();
|
||||
|
||||
const Rect menuRect = Rect::Create(0, 0, kMenuBarHeight, width);
|
||||
|
||||
if (m_menuBarGraf == nullptr)
|
||||
{
|
||||
int depth = 0;
|
||||
|
||||
switch (pixelFormat)
|
||||
{
|
||||
case GpPixelFormats::k8BitStandard:
|
||||
depth = 8;
|
||||
break;
|
||||
default:
|
||||
PL_NotYetImplemented();
|
||||
return;
|
||||
}
|
||||
|
||||
if (qdManager->NewGWorld(&m_menuBarGraf, depth, menuRect, nullptr, nullptr, 0) != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
CGraf *graf = m_menuBarGraf;
|
||||
|
||||
assert(graf);
|
||||
|
||||
if (static_cast<unsigned int>(graf->m_port.GetRect().right) != width)
|
||||
{
|
||||
if (!graf->m_port.Resize(menuRect))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
RefreshMenuLayout();
|
||||
|
||||
CGraf *oldGraf;
|
||||
GDHandle oldDevice;
|
||||
GetGWorld(&oldGraf, &oldDevice);
|
||||
|
||||
SetGWorld(m_menuBarGraf, nullptr);
|
||||
|
||||
PortabilityLayer::QDState *qdState = qdManager->GetState();
|
||||
|
||||
qdState->SetForeColor(gs_barMidColor);
|
||||
PaintRect(&menuRect);
|
||||
|
||||
qdState->SetForeColor(gs_barBrightColor);
|
||||
|
||||
// Top stripe
|
||||
{
|
||||
const Rect rect = Rect::Create(0, 0, 1, static_cast<int16_t>(width) - 1);
|
||||
PaintRect(&rect);
|
||||
}
|
||||
|
||||
// Left stripe
|
||||
{
|
||||
const Rect rect = Rect::Create(0, 0, kMenuBarHeight - 1, 1);
|
||||
PaintRect(&rect);
|
||||
}
|
||||
|
||||
qdState->SetForeColor(gs_barDarkColor);
|
||||
|
||||
// Bottom stripe
|
||||
{
|
||||
const Rect rect = Rect::Create(kMenuBarHeight - 2, 1, kMenuBarHeight - 1, width);
|
||||
PaintRect(&rect);
|
||||
}
|
||||
|
||||
// Right stripe
|
||||
{
|
||||
const Rect rect = Rect::Create(0, width - 1, kMenuBarHeight - 1, width);
|
||||
PaintRect(&rect);
|
||||
}
|
||||
|
||||
qdState->SetForeColor(gs_barBottomEdgeColor);
|
||||
|
||||
// Bottom edge
|
||||
{
|
||||
const Rect rect = Rect::Create(kMenuBarHeight - 1, 0, kMenuBarHeight, width);
|
||||
PaintRect(&rect);
|
||||
}
|
||||
|
||||
PixMapHandle pixMap = m_menuBarGraf->m_port.GetPixMap();
|
||||
|
||||
// Round corners
|
||||
gs_barTopLeftCornerGraphic.DrawToPixMap(pixMap, 0, 0);
|
||||
gs_barTopRightCornerGraphic.DrawToPixMap(pixMap, static_cast<int16_t>(width) - static_cast<int16_t>(gs_barTopRightCornerGraphic.m_width), 0);
|
||||
|
||||
qdState->SetForeColor(gs_barNormalTextColor);
|
||||
TextFont(systemFont);
|
||||
TextSize(kMenuFontSize);
|
||||
|
||||
// Text items
|
||||
{
|
||||
Menu **menuHdl = m_firstMenu;
|
||||
while (menuHdl)
|
||||
{
|
||||
Menu *menu = *menuHdl;
|
||||
|
||||
if (menu->stringBlobHandle)
|
||||
{
|
||||
size_t xCoordinate = menu->cumulativeOffset + (menu->menuIndex * 2) * kMenuBarItemPadding + kMenuBarInitialPadding;
|
||||
|
||||
if (menu->isIcon)
|
||||
{
|
||||
if (m_iconGraphic)
|
||||
m_iconGraphic->DrawToPixMapWithMask(pixMap, m_iconMask, xCoordinate, kMenuBarIconYOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
qdState->m_penPos.h = xCoordinate;
|
||||
qdState->m_penPos.v = kMenuBarTextYOffset;
|
||||
DrawString(PLPasStr(static_cast<const uint8_t*>(menu->stringBlobHandle->m_contents)));
|
||||
}
|
||||
}
|
||||
|
||||
menuHdl = menu->nextMenu;
|
||||
}
|
||||
}
|
||||
|
||||
SetGWorld(oldGraf, oldDevice);
|
||||
|
||||
m_menuBarGraf->m_port.SetDirty(QDPortDirtyFlag_Contents);
|
||||
}
|
||||
|
||||
void MenuManagerImpl::RenderFrame(IGpDisplayDriver *displayDriver)
|
||||
{
|
||||
if (m_menuBarGraf)
|
||||
{
|
||||
m_menuBarGraf->PushToDDSurface(displayDriver);
|
||||
|
||||
if (m_menuBarGraf->m_ddSurface)
|
||||
{
|
||||
const PixMap *pixMap = *m_menuBarGraf->m_port.GetPixMap();
|
||||
const size_t width = pixMap->m_rect.right - pixMap->m_rect.left;
|
||||
const size_t height = pixMap->m_rect.bottom - pixMap->m_rect.top;
|
||||
displayDriver->DrawSurface(m_menuBarGraf->m_ddSurface, 0, 0, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuManagerImpl::RefreshMenuLayout()
|
||||
{
|
||||
if (m_haveMenuLayout)
|
||||
return;
|
||||
|
||||
PortabilityLayer::FontManager *fontManager = PortabilityLayer::FontManager::GetInstance();
|
||||
|
||||
PortabilityLayer::FontFamily *fontFamily = PortabilityLayer::FontManager::GetInstance()->GetSystemFont(kMenuFontSize, kMenuFontFlags);
|
||||
if (!fontFamily)
|
||||
return;
|
||||
|
||||
PortabilityLayer::RenderedFont *rfont = PortabilityLayer::FontManager::GetInstance()->GetRenderedFontFromFamily(fontFamily, kMenuFontSize, kMenuFontFlags);
|
||||
if (!rfont)
|
||||
return;
|
||||
|
||||
unsigned int index = 0;
|
||||
size_t measuredWidth = 0;
|
||||
|
||||
Menu **menuHdl = m_firstMenu;
|
||||
while (menuHdl)
|
||||
{
|
||||
Menu *menu = *menuHdl;
|
||||
|
||||
menu->menuIndex = index++;
|
||||
menu->cumulativeOffset = measuredWidth;
|
||||
|
||||
const PLPasStr pascalStr = PLPasStr(static_cast<const uint8_t*>(menu->stringBlobHandle->m_contents));
|
||||
|
||||
if (pascalStr.Length() == 1 && pascalStr.UChars()[0] == 0x14)
|
||||
{
|
||||
measuredWidth += 16;
|
||||
menu->isIcon = true;
|
||||
}
|
||||
else
|
||||
measuredWidth += rfont->MeasureString(pascalStr.UChars(), pascalStr.Length());
|
||||
|
||||
menuHdl = menu->nextMenu;
|
||||
}
|
||||
|
||||
m_haveMenuLayout = true;
|
||||
}
|
||||
|
||||
MenuManagerImpl *MenuManagerImpl::GetInstance()
|
||||
{
|
||||
return &ms_instance;
|
||||
|
||||
Reference in New Issue
Block a user