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:
parent
93c797329e
commit
502211495b
|
@ -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 },
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
3
ui.h
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user