home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
215
/
DDJ9302.ZIP
/
DFPP01.ZIP
/
POPDOWN.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-21
|
8KB
|
382 lines
// ------------- popdown.cpp
#include <ctype.h>
#include "desktop.h"
#include "popdown.h"
#include "menusel.h"
void PopDown::OpenWindow()
{
windowtype = PopdownWindow;
if (windowstate == CLOSED)
ListBox::OpenWindow();
SetAttribute(BORDER | SHADOW | SAVESELF | NOCLIP);
selection = 0;
DblBorder = False;
isopen = False;
SetColors();
iscascaded = False;
if (selections != NULL) {
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;
}
}
void PopDown::CloseWindow()
{
if (selections != NULL) {
// --- delete all cascader popdowns
for (int i = 0; ; i++) {
MenuSelection &ms = **(selections+i);
if (ms.type == TERMINATOR)
break;
if (ms.type == CASCADER && ms.cascade != NULL)
delete ms.cascade;
}
}
ListBox::CloseWindow();
}
void PopDown::OpenMenu(int left, int top)
{
Rect rc(0, 0, desktop.screen().Width()-1, desktop.screen().Height()-1);
DFWindow *Wnd = parent;
while (Wnd != NULL && Wnd->WindowType() == PopdownWindow)
Wnd = Wnd->Parent();
if (Wnd != NULL && (Wnd = Wnd->Parent()) != NULL) {
Rect rc = Wnd->ClientRect();
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
}
void PopDown::CloseMenu(Bool SendESC)
{
if (isopen) {
// ------- close any open cascaded menus
PopDown *Wnd = (PopDown *)first;
while (Wnd != NULL) {
Wnd->CloseMenu(False);
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]->type != TERMINATOR; i++) {
if (selections[i]->type != SEPARATOR) {
int lblen = (selections[i]->label)->Strlen()-1;
txlen = max(txlen, lblen);
}
}
menuwidth = txlen+4;
menuheight = i;
}
// -------- set the fg/bg colors for the window
void PopDown::SetColors()
{
colors.fg = BLACK;
colors.bg = CYAN;
colors.sfg = BLACK;
colors.sbg = LIGHTGRAY;
colors.ffg = BLACK;
colors.fbg = CYAN;
colors.hfg = DARKGRAY; // Inactive FG
colors.hbg = CYAN; // Inactive FG
shortcutfg = RED;
}
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;
}
}
void PopDown::ClearSelection()
{
if (selection != -1) {
int sel = selection;
selection = -1;
DisplayMenuLine(sel);
}
}
void PopDown::SetSelection(int sel)
{
ClearSelection();
if (sel >= 0 && sel < wlines) {
selection = sel;
DisplayMenuLine(sel);
}
}
void PopDown::Paint()
{
if (text == NULL)
ListBox::Paint();
else {
for (int i = 0; i < wlines; i++) {
if (selections[i]->type == TOGGLE) {
char *cp = TextLine(i);
if (selections[i]->toggle == On)
*cp = CheckMark();
else
*cp = ' ';
}
DisplayMenuLine(i);
}
}
}
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);
}
}
}
}
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;
}
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;
}
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(False);
if (parent != NULL) {
parent->Keyboard(key);
return;
}
break;
default:
break;
}
ListBox::Keyboard(key);
}
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;
}
void PopDown::DoubleClick(int mx, int my)
{
if (!rect.Inside(mx, my)) {
CloseMenu(False);
if (parent)
parent->DoubleClick(mx, my);
}
}
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 = inWindow(mx, my);
if (!(Wnd == parent && my == Top()-1 &&
mx >= Left() && mx <= Right())) {
CloseMenu(ParentisMenu());
if (Wnd != NULL && Wnd != desktop.InFocus())
Wnd->SetFocus();
}
}
}
void PopDown::Choose()
{
MenuSelection &ms = *selections[selection];
if (ms.isEnabled()) {
if (ms.type == CASCADER && ms.cascade != NULL)
ms.cascade->OpenMenu(Right(), Top()+selection);
else {
if (ms.type == TOGGLE) {
ms.InvertToggle();
char *cp = TextLine(selection);
if (*cp == CheckMark())
*cp = ' ';
else
*cp = CheckMark();
DisplayMenuLine(selection);
}
if (ms.cmdfunction != NULL) {
CloseMenu(iscascaded ? False : ParentisMenu());
DFWindow *par = Parent();
while (ParentisMenu(*par)) {
par->Keyboard(ESC);
par = par->Parent();
}
(par->*ms.cmdfunction)();
}
}
}
else
desktop.speaker().Beep();
}
Bool PopDown::ParentisMenu(DFWindow &wnd)
{
if (wnd.Parent() != NULL) {
WndType wt = wnd.Parent()->WindowType();
return (Bool) (wt == MenubarWindow || wt == PopdownWindow);
}
return False;
}