Category : C Source Code
Archive   : DFPP03.ZIP
Filename : POPDOWN.CPP

 
Output of file : POPDOWN.CPP contained in archive : DFPP03.ZIP
// ------------- popdown.cpp

#include
#include "dflatpp.h"

static Color col = {
BLACK, // fg
CYAN, // bg
BLACK, // selected fg
LIGHTGRAY, // selected bg
BLACK, // frame fg
CYAN, // frame bg
DARKGRAY, // inactive fg
CYAN // inactive bg
};

PopDown::PopDown(DFWindow *par, MenuSelection **Selections)
: ListBox(5, 5, par)
{
windowtype = PopdownWindow;
selections = Selections;
SetAttribute(BORDER | SHADOW | SAVESELF);
selection = 0;
DblBorder = False;
isopen = False;
iscascaded = False;
if (selections != 0) {
MenuDimensions();
SetTextLength(menuwidth * menuheight);
for (int i = 0; i < menuheight; i++) {
MenuSelection &ms = **(selections+i);
BuildMenuLine(i);
if (ms.type == CASCADER) {
ms.cascade = new PopDown(this, ms.cascaders);
ms.cascade->isCascaded() = True;
}
}
rect.Right() = rect.Left() + menuwidth;
rect.Bottom() = rect.Top() + menuheight + 1;
}
colors = col;
shortcutfg = RED;
}

// ---- shut down a popdown menu
void PopDown::CloseWindow()
{
if (selections != 0) {
// --- delete all cascader popdowns
for (int i = 0; selections[i]; i++) {
MenuSelection &ms = *selections[i];
if (ms.type == CASCADER && ms.cascade != 0)
delete ms.cascade;
}
}
ListBox::CloseWindow();
}

// ------- pop down the menu
void PopDown::OpenMenu(int left, int top)
{
Rect rc(0, 0, desktop.screen().Width()-1,
desktop.screen().Height()-1);
DFWindow *Wnd = Parent();
while (Wnd != 0 && Wnd->WindowType() == PopdownWindow)
Wnd = Wnd->Parent();
if (Wnd != 0 && (Wnd = Wnd->Parent()) != 0) {
Rect rc = Wnd->ClientRect();
if (Parent()->WindowType() == MenubarWindow)
if (Wnd->WindowType() == ApplicationWindow)
if (Wnd->Attribute() & TOOLBAR)
rc = Rect(rc.Left(), rc.Top()-3, rc.Right(), rc.Bottom());
left = min(max(left, rc.Left()),
rc.Right() - ClientWidth());
top = min(max(top, rc.Top()),
rc.Bottom() - ClientHeight());
}
left = min(max(left, rc.Left()),
rc.Right()-ClientWidth()-1);
top = min(max(top, rc.Top()),
rc.Bottom()-ClientHeight()-1);
isopen = True;
Move(left, top);
CaptureFocus();
Paint(); // in case a command attribute changed
}

// ---------- deactivate the popdown menu
void PopDown::CloseMenu(Bool SendESC)
{
if (isopen) {
// ------- close any open cascaded menus
PopDown *Wnd = (PopDown *)First();
while (Wnd != 0) {
Wnd->CloseMenu();
Wnd = (PopDown *) (Wnd->Next());
}
Hide();
isopen = False;
ReleaseFocus();
if (Parent() && !iscascaded && SendESC)
Parent()->Keyboard(ESC);
}
}

void PopDown::Show()
{
if (isopen)
ListBox::Show();
}

// -------- build a menu line
void PopDown::BuildMenuLine(int sel)
{
int wd = menuwidth;
String ln;
if (selections[sel]->type == SEPARATOR)
ln = String(--wd, LINE);
else {
ln = String(" ");
ln += *(selections[sel]->label);
int r = wd-ln.Strlen();
ln += String(r, ' ');
if (selections[sel]->type == CASCADER)
ln[wd-1] = CASCADEPOINTER;
}
AddText(ln);
}

// -------- compute menu width
void PopDown::MenuDimensions()
{
int txlen = 0;
for (int i = 0; selections[i] != 0; i++) {
if (selections[i]->type != SEPARATOR) {
int lblen = (selections[i]->label)->Strlen()-1;
txlen = max(txlen, lblen);
}
}
menuwidth = txlen+4;
menuheight = i;
}

// ------ display a menu line
void PopDown::DisplayMenuLine(int lno)
{
if (isopen) {
int fg, bg;
int isActive = selections[lno]->isEnabled();
int sfg = shortcutfg;
if (lno == selection) {
fg = colors.sfg;
bg = colors.sbg;
}
else if (isActive) {
fg = colors.fg;
bg = colors.bg;
}
else {
fg = colors.hfg;
bg = colors.hbg;
}
if (!isActive)
shortcutfg = fg;
WriteShortcutLine(lno, fg, bg);
shortcutfg = sfg;
}
}

// ------ set no selection current
void PopDown::ClearSelection()
{
if (selection != -1) {
int sel = selection;
selection = -1;
DisplayMenuLine(sel);
}
}

// ------ set a current menu selection
void PopDown::SetSelection(int sel)
{
ClearSelection();
if (sel >= 0 && sel < wlines) {
selection = sel;
DisplayMenuLine(sel);
}
}

// ---------- paint the menu
void PopDown::Paint()
{
if (text == 0)
ListBox::Paint();
else {
for (int i = 0; i < wlines; i++) {
if (selections[i]->type == TOGGLE) {
int off = TextLine(i) - (const char *)*text;
if (selections[i]->toggle == On)
(*text)[off] = CheckMark();
else
(*text)[off] = ' ';
}
DisplayMenuLine(i);
}
}
}

// --------- paint the menu's border
void PopDown::Border()
{
if (isopen && isVisible()) {
int fg = colors.ffg;
int bg = colors.fbg;
int rt = Width()-1;
ListBox::Border();
for (int i = 0; i < wlines; i++) {
if (selections[i]->type == SEPARATOR) {
WriteWindowChar(LEDGE, 0, i+1, fg, bg);
WriteWindowChar(REDGE, rt, i+1, fg, bg);
}
}
}
}

// ------- test for a menu selection accelerator key
Bool PopDown::AcceleratorKey(int key)
{
for (int i = 0; i < wlines; i++) {
MenuSelection &ms = **(selections+i);
if (key == ms.accelerator) {
SetSelection(i);
Choose();
return True;
}
}
return False;
}

// ------- test for a menu selection shortcut key
Bool PopDown::ShortcutKey(int key)
{
key = tolower(key);
for (int i = 0; i < wlines; i++) {
MenuSelection &ms = **(selections+i);
int off = ms.label->FindChar(SHORTCUTCHAR);
if (off != -1) {
String &cp = *ms.label;
int c = cp[off+1];
if (key == tolower(c)) {
SetSelection(i);
Choose();
return True;
}
}
}
return False;
}

// ----- keystroke while menu is popped down
void PopDown::Keyboard(int key)
{
if (AcceleratorKey(key))
return;
if (ShortcutKey(key))
return;
switch (key) {
case UP:
if (selection == 0) {
SetSelection(wlines-1);
return;
}
if (selections[selection-1]->type == SEPARATOR) {
SetSelection(selection-2);
return;
}
break;
case DN:
if (selection == wlines-1) {
SetSelection(0);
return;
}
if (selections[selection+1]->type == SEPARATOR) {
SetSelection(selection+2);
return;
}
break;
case ESC:
CloseMenu(ParentisMenu());
return;
case FWD:
case BS:
CloseMenu();
if (Parent() != 0) {
Parent()->Keyboard(key);
return;
}
break;
default:
break;
}
ListBox::Keyboard(key);
}

// ----- shift key status changed
void PopDown::ShiftChanged(int sk)
{
if (sk & ALTKEY)
CloseMenu(ParentisMenu());
}

// ---------- Left mouse button was clicked
void PopDown::LeftButton(int mx, int my)
{
if (ClientRect().Inside(mx, my)) {
if (my != prevmouseline) {
int y = my - ClientTop();
if (selections[y]->type != SEPARATOR)
SetSelection(y);
}
}
else if (!rect.Inside(mx, my)) {
if (Parent() && my == Parent()->Bottom())
Parent()->LeftButton(mx, my);
}
prevmouseline = my;
prevmousecol = mx;
}

// ---------- Left mouse button was double-clicked
void PopDown::DoubleClick(int mx, int my)
{
if (!rect.Inside(mx, my)) {
CloseMenu();
if (Parent())
Parent()->DoubleClick(mx, my);
}
}

// ---------- Left mouse button was released
void PopDown::ButtonReleased(int mx, int my)
{
if (ClientRect().Inside(mx, my)) {
if (prevmouseline == my && prevmousecol == mx)
if (selections[my-ClientTop()]->type != SEPARATOR)
Choose();
}
else if (!rect.Inside(mx, my)) {
DFWindow *Wnd = desktop.inWindow(mx, my);
if (!(Wnd == Parent() && my == Top()-1 &&
mx >= Left() && mx <= Right())) {
CloseMenu(ParentisMenu());
if (Wnd != 0 && Wnd != desktop.InFocus())
Wnd->SetFocus();
}
}
}

// --------- user chose a menu selection
void PopDown::Choose()
{
MenuSelection &ms = *selections[selection];
if (ms.isEnabled()) {
if (ms.type == CASCADER && ms.cascade != 0)
// -------- cascaded menu
ms.cascade->OpenMenu(Right(), Top()+selection);
else {
if (ms.type == TOGGLE) {
// ---- toggle selection
ms.InvertToggle();
const char *cp = TextLine(selection);
int off = cp - (const char *)*text;
if (*cp == CheckMark())
(*text)[off] = ' ';
else
(*text)[off] = CheckMark();
DisplayMenuLine(selection);
}
if (ms.cmdfunction != 0) {
// ---- there is a function associated
DFWindow *wnd = (PopDown *) this;
// --- close all menus
while (wnd &&
wnd->WindowType() == PopdownWindow) {
((PopDown *)wnd)->CloseMenu();
wnd = (wnd->Parent());
}
if (wnd && wnd->WindowType() == MenubarWindow){
if (wnd == desktop.InFocus())
wnd->Keyboard(ESC);
wnd = (wnd->Parent());
}
if (wnd)
// ---- execute the function
(((Application *)wnd)->*ms.cmdfunction)();
}
}
}
else
desktop.speaker().Beep(); // disabled selection
}

inline Bool isMenu(DFWindow *wnd)
{
if (wnd != 0) {
WndType wt = wnd->WindowType();
return (Bool) (wt==MenubarWindow || wt==PopdownWindow);
}
return False;
}

// ----- test for the parent as menu or menubar
Bool PopDown::ParentisMenu(DFWindow &wnd)
{
return isMenu(wnd.Parent());
}



  3 Responses to “Category : C Source Code
Archive   : DFPP03.ZIP
Filename : POPDOWN.CPP

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/