Add the file open/save user interface. This includes a list of

recently opened files, that is saved in the registry and displayed
in a separate popup menu.

[git-p4: depot-paths = "//depot/solvespace/": change = 1752]
This commit is contained in:
Jonathan Westhues 2008-05-28 02:10:31 -08:00
parent 93c797329e
commit 502211495b
5 changed files with 157 additions and 21 deletions

View File

@ -14,6 +14,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
{ 0, "&File", 0, NULL }, { 0, "&File", 0, NULL },
{ 1, "&New\tCtrl+N", MNU_NEW, 'N'|C, mFile }, { 1, "&New\tCtrl+N", MNU_NEW, 'N'|C, mFile },
{ 1, "&Open...\tCtrl+O", MNU_OPEN, 'O'|C, mFile }, { 1, "&Open...\tCtrl+O", MNU_OPEN, 'O'|C, mFile },
{10, "&Open Recent", MNU_OPEN_RECENT, 0, mFile },
{ 1, "&Save\tCtrl+S", MNU_SAVE, 'S'|C, mFile }, { 1, "&Save\tCtrl+S", MNU_SAVE, 'S'|C, mFile },
{ 1, "Save &As...", MNU_SAVE_AS, 0, mFile }, { 1, "Save &As...", MNU_SAVE_AS, 0, mFile },
{ 1, NULL, 0, 0, NULL }, { 1, NULL, 0, 0, NULL },
@ -37,17 +38,17 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
{ 1, "Dimensions in &Inches", MNU_UNITS_INCHES, 0, mView }, { 1, "Dimensions in &Inches", MNU_UNITS_INCHES, 0, mView },
{ 1, "Dimensions in &Millimeters", MNU_UNITS_MM, 0, mView }, { 1, "Dimensions in &Millimeters", MNU_UNITS_MM, 0, mView },
{ 0, "&Group", 0, 0, NULL }, { 0, "&New Feature", 0, 0, NULL },
{ 1, "New &Drawing in 3d\tShift+Ctrl+D", MNU_GROUP_3D, 'D'|S|C, mGrp }, { 1, "&Drawing in 3d\tShift+Ctrl+D", MNU_GROUP_3D, 'D'|S|C, mGrp },
{ 1, "New Drawing in Workplane\tShift+Ctrl+W",MNU_GROUP_WRKPL, 'W'|S|C, mGrp }, { 1, "Drawing in Workplane\tShift+Ctrl+W", MNU_GROUP_WRKPL, 'W'|S|C, mGrp },
{ 1, NULL, 0, NULL }, { 1, NULL, 0, NULL },
{ 1, "New Step &Translating\tShift+Ctrl+R", MNU_GROUP_TRANS, 'T'|S|C,mGrp }, { 1, "Step &Translating\tShift+Ctrl+R", MNU_GROUP_TRANS, 'T'|S|C,mGrp },
{ 1, "New Step &Rotating\tShift+Ctrl+T", MNU_GROUP_ROT, 'R'|S|C,mGrp }, { 1, "Step &Rotating\tShift+Ctrl+T", MNU_GROUP_ROT, 'R'|S|C,mGrp },
{ 1, NULL, 0, 0, NULL }, { 1, NULL, 0, 0, NULL },
{ 1, "New Extrusion\tShift+Ctrl+X", MNU_GROUP_EXTRUDE, 'X'|S|C,mGrp }, { 1, "Extrusion\tShift+Ctrl+X", MNU_GROUP_EXTRUDE, 'X'|S|C,mGrp },
{ 1, NULL, 0, 0, NULL }, { 1, NULL, 0, 0, NULL },
{ 1, "New Boolean Difference", 0, 0, NULL }, { 1, "Import...\tShift+Ctrl+I", MNU_GROUP_IMPORT, 'I'|S|C,mGrp },
{ 1, "New Boolean Union", 0, 0, NULL }, {11, "Import Recent", MNU_GROUP_RECENT, 0, mGrp },
{ 0, "&Request", 0, NULL }, { 0, "&Request", 0, NULL },
{ 1, "Draw in &Workplane\tW", MNU_SEL_WORKPLANE, 'W', mReq }, { 1, "Draw in &Workplane\tW", MNU_SEL_WORKPLANE, 'W', mReq },

View File

@ -6,9 +6,17 @@ void SolveSpace::Init(char *cmdLine) {
if(strlen(cmdLine) == 0) { if(strlen(cmdLine) == 0) {
NewFile(); NewFile();
} else { } else {
LoadFromFile(cmdLine); if(LoadFromFile(cmdLine)) {
strcpy(saveFile, cmdLine);
} else {
NewFile();
}
} }
AfterNewFile();
}
void SolveSpace::AfterNewFile(void) {
GenerateAll(false, 0, INT_MAX); GenerateAll(false, 0, INT_MAX);
TW.Init(); TW.Init();
@ -302,25 +310,85 @@ void SolveSpace::SolveGroup(hGroup hg) {
FreeAllTemporary(); FreeAllTemporary();
} }
void SolveSpace::RemoveFromRecentList(char *file) {
int src, dest;
dest = 0;
for(src = 0; src < MAX_RECENT; src++) {
if(strcmp(file, RecentFile[src]) != 0) {
if(src != dest) strcpy(RecentFile[dest], RecentFile[src]);
dest++;
}
}
while(dest < MAX_RECENT) strcpy(RecentFile[dest++], "");
RefreshRecentMenus();
}
void SolveSpace::AddToRecentList(char *file) {
RemoveFromRecentList(file);
int src;
for(src = MAX_RECENT - 2; src >= 0; src--) {
strcpy(RecentFile[src+1], RecentFile[src]);
}
strcpy(RecentFile[0], file);
RefreshRecentMenus();
}
void SolveSpace::MenuFile(int id) { void SolveSpace::MenuFile(int id) {
char *slvsPattern =
"SolveSpace Models (*.slvs)\0*.slvs\0All Files (*)\0*\0\0";
char *slvsExt = "slvs";
if(id >= RECENT_OPEN && id < (RECENT_OPEN+MAX_RECENT)) {
char newFile[MAX_PATH];
strcpy(newFile, RecentFile[id-RECENT_OPEN]);
RemoveFromRecentList(newFile);
if(SS.LoadFromFile(newFile)) {
strcpy(SS.saveFile, newFile);
AddToRecentList(newFile);
} else {
strcpy(SS.saveFile, "");
SS.NewFile();
}
SS.AfterNewFile();
return;
}
switch(id) { switch(id) {
case GraphicsWindow::MNU_NEW: case GraphicsWindow::MNU_NEW:
strcpy(SS.saveFile, "");
SS.NewFile(); SS.NewFile();
SS.GenerateAll(false); SS.AfterNewFile();
SS.TW.Init();
SS.GW.Init();
SS.TW.Show();
break; break;
case GraphicsWindow::MNU_OPEN: case GraphicsWindow::MNU_OPEN: {
char newFile[MAX_PATH] = "";
if(GetOpenFile(newFile, slvsExt, slvsPattern)) {
if(SS.LoadFromFile(newFile)) {
strcpy(SS.saveFile, newFile);
AddToRecentList(newFile);
} else {
strcpy(SS.saveFile, "");
SS.NewFile();
}
SS.AfterNewFile();
}
break; break;
}
case GraphicsWindow::MNU_SAVE: case GraphicsWindow::MNU_SAVE:
SS.SaveToFile("t.slvs"); case GraphicsWindow::MNU_SAVE_AS: {
break; char newFile[MAX_PATH];
strcpy(newFile, SS.saveFile);
if(id == GraphicsWindow::MNU_SAVE_AS || strlen(newFile)==0) {
if(!GetSaveFile(newFile, slvsExt, slvsPattern)) break;
}
case GraphicsWindow::MNU_SAVE_AS: if(SS.SaveToFile(newFile)) {
AddToRecentList(newFile);
strcpy(SS.saveFile, newFile);
}
break; break;
}
case GraphicsWindow::MNU_EXIT: case GraphicsWindow::MNU_EXIT:
break; break;

View File

@ -42,6 +42,12 @@ class ExprVector;
class ExprQuaternion; class ExprQuaternion;
// From the platform-specific code. // From the platform-specific code.
#define MAX_RECENT 8
#define RECENT_OPEN (0xf000)
#define RECENT_IMPORT (0xf100)
extern char RecentFile[MAX_RECENT][MAX_PATH];
void RefreshRecentMenus(void);
int SaveFileYesNoCancel(void); int SaveFileYesNoCancel(void);
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern); BOOL GetSaveFile(char *file, char *defExtension, char *selPattern);
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern); BOOL GetOpenFile(char *file, char *defExtension, char *selPattern);
@ -202,6 +208,9 @@ public:
FILE *fh; FILE *fh;
void Init(char *cmdLine); void Init(char *cmdLine);
void AfterNewFile(void);
static void RemoveFromRecentList(char *file);
static void AddToRecentList(char *file);
char saveFile[MAX_PATH]; char saveFile[MAX_PATH];
bool unsaved; bool unsaved;

3
ui.h
View File

@ -110,6 +110,7 @@ public:
// File // File
MNU_NEW = 100, MNU_NEW = 100,
MNU_OPEN, MNU_OPEN,
MNU_OPEN_RECENT,
MNU_SAVE, MNU_SAVE,
MNU_SAVE_AS, MNU_SAVE_AS,
MNU_EXIT, MNU_EXIT,
@ -140,6 +141,8 @@ public:
MNU_GROUP_EXTRUDE, MNU_GROUP_EXTRUDE,
MNU_GROUP_ROT, MNU_GROUP_ROT,
MNU_GROUP_TRANS, MNU_GROUP_TRANS,
MNU_GROUP_IMPORT,
MNU_GROUP_RECENT,
// Constrain // Constrain
MNU_DISTANCE_DIA, MNU_DISTANCE_DIA,
MNU_ANGLE, MNU_ANGLE,

View File

@ -33,11 +33,14 @@ int TextWndHalfRows; // The height of our window, in half-row units
HWND GraphicsWnd; HWND GraphicsWnd;
HGLRC GraphicsHpgl; HGLRC GraphicsHpgl;
HWND GraphicsEditControl; HWND GraphicsEditControl;
HMENU SubMenus[100];
struct { struct {
int x, y; int x, y;
} LastMousePos; } LastMousePos;
char RecentFile[MAX_RECENT][MAX_PATH];
HMENU SubMenus[100];
HMENU RecentOpenMenu, RecentImportMenu;
int ClientIsSmallerBy; int ClientIsSmallerBy;
HFONT FixedFont, LinkFont; HFONT FixedFont, LinkFont;
@ -604,12 +607,22 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
case WM_COMMAND: { case WM_COMMAND: {
if(HIWORD(wParam) == 0) { if(HIWORD(wParam) == 0) {
int id = LOWORD(wParam); int id = LOWORD(wParam);
for(int i = 0; SS.GW.menu[i].level >= 0; i++) { if((id >= RECENT_OPEN && id < (RECENT_OPEN + MAX_RECENT))) {
SolveSpace::MenuFile(id);
break;
}
if((id >= RECENT_IMPORT && id < (RECENT_IMPORT + MAX_RECENT))) {
Group::MenuGroup(id);
break;
}
int i;
for(i = 0; SS.GW.menu[i].level >= 0; i++) {
if(id == SS.GW.menu[i].id) { if(id == SS.GW.menu[i].id) {
(SS.GW.menu[i].fn)((GraphicsWindow::MenuId)id); (SS.GW.menu[i].fn)((GraphicsWindow::MenuId)id);
break; break;
} }
} }
if(SS.GW.menu[i].level < 0) oops();
} }
break; break;
} }
@ -710,6 +723,25 @@ void EnableMenuById(int id, BOOL enabled)
{ {
MenuById(id, enabled, FALSE); MenuById(id, enabled, FALSE);
} }
static void DoRecent(HMENU m, int base)
{
while(DeleteMenu(m, 0, MF_BYPOSITION))
;
int i, c = 0;
for(i = 0; i < MAX_RECENT; i++) {
char *s = RecentFile[i];
if(*s) {
AppendMenu(m, MF_STRING, base+i, s);
c++;
}
}
if(c == 0) AppendMenu(m, MF_STRING | MF_GRAYED, 0, "(no recent files)");
}
void RefreshRecentMenus(void)
{
DoRecent(RecentOpenMenu, RECENT_OPEN);
DoRecent(RecentImportMenu, RECENT_IMPORT);
}
HMENU CreateGraphicsWindowMenus(void) HMENU CreateGraphicsWindowMenus(void)
{ {
@ -728,14 +760,23 @@ HMENU CreateGraphicsWindowMenus(void)
if(subMenu >= arraylen(SubMenus)) oops(); if(subMenu >= arraylen(SubMenus)) oops();
SubMenus[subMenu] = m; SubMenus[subMenu] = m;
subMenu++; subMenu++;
} else { } else if(SS.GW.menu[i].level == 1) {
if(SS.GW.menu[i].label) { if(SS.GW.menu[i].label) {
AppendMenu(m, MF_STRING, SS.GW.menu[i].id, SS.GW.menu[i].label); AppendMenu(m, MF_STRING, SS.GW.menu[i].id, SS.GW.menu[i].label);
} else { } else {
AppendMenu(m, MF_SEPARATOR, SS.GW.menu[i].id, ""); AppendMenu(m, MF_SEPARATOR, SS.GW.menu[i].id, "");
} }
} } else if(SS.GW.menu[i].level == 10) {
RecentOpenMenu = CreateMenu();
AppendMenu(m, MF_STRING | MF_POPUP,
(UINT_PTR)RecentOpenMenu, SS.GW.menu[i].label);
} else if(SS.GW.menu[i].level == 11) {
RecentImportMenu = CreateMenu();
AppendMenu(m, MF_STRING | MF_POPUP,
(UINT_PTR)RecentImportMenu, SS.GW.menu[i].label);
} else oops();
} }
RefreshRecentMenus();
return top; return top;
} }
@ -819,6 +860,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
InitCommonControls(); InitCommonControls();
int i;
for(i = 0; i < MAX_RECENT; i++) {
char name[100];
sprintf(name, "RecentFile_%d", i);
ThawStringF(RecentFile[i], MAX_PATH, FREEZE_SUBKEY, name);
}
// A monospaced font // A monospaced font
FixedFont = CreateFont(TEXT_HEIGHT-4, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE, FixedFont = CreateFont(TEXT_HEIGHT-4, TEXT_WIDTH, 0, 0, FW_REGULAR, FALSE,
FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
@ -860,8 +908,15 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
} }
// Write everything back to the registry
FreezeWindowPos(TextWnd); FreezeWindowPos(TextWnd);
FreezeWindowPos(GraphicsWnd); FreezeWindowPos(GraphicsWnd);
for(i = 0; i < MAX_RECENT; i++) {
char name[100];
sprintf(name, "RecentFile_%d", i);
FreezeStringF(RecentFile[i], FREEZE_SUBKEY, name);
}
return 0; return 0;
} }