tabs bar context menu

This commit is contained in:
stefan schippers 2023-10-25 11:43:43 +02:00
parent d83acf710d
commit 3d4113ad26
6 changed files with 199 additions and 38 deletions

View File

@ -1511,13 +1511,13 @@ void symbol_in_new_window(int new_process)
if(xctx->lastsel !=1 || xctx->sel_array[0].type!=ELEMENT) {
my_strncpy(filename, xctx->sch[xctx->currsch], S(filename));
if(new_process) new_xschem_process(filename, 1);
else new_schematic("create", NULL, filename);
else new_schematic("create", NULL, filename, 1);
}
else {
my_strncpy(filename, abs_sym_path(tcl_hook2(xctx->inst[xctx->sel_array[0].n].name), ""), S(filename));
if(!check_loaded(filename, win_path)) {
if(new_process) new_xschem_process(filename, 1);
else new_schematic("create", NULL, filename);
else new_schematic("create", NULL, filename, 1);
}
}
}
@ -1530,7 +1530,7 @@ void schematic_in_new_window(int new_process)
rebuild_selected_array();
if(xctx->lastsel !=1 || xctx->sel_array[0].type!=ELEMENT) {
if(new_process) new_xschem_process(xctx->sch[xctx->currsch], 0);
else new_schematic("create", NULL, xctx->sch[xctx->currsch]);
else new_schematic("create", NULL, xctx->sch[xctx->currsch], 1);
}
else {
if( /* do not descend if not subcircuit */
@ -1547,7 +1547,7 @@ void schematic_in_new_window(int new_process)
get_sch_from_sym(filename, xctx->inst[xctx->sel_array[0].n].ptr+ xctx->sym, xctx->sel_array[0].n);
if(!check_loaded(filename, win_path)) {
if(new_process) new_xschem_process(filename, 0);
else new_schematic("create", NULL, filename);
else new_schematic("create", NULL, filename, 1);
}
}
}

View File

@ -1099,10 +1099,10 @@ int rstate; /* (reduced state, without ShiftMask) */
if( xctx->semaphore >= 1 || event == Expose) {
dbg(1, "callback(): semaphore >=2 (or Expose) switching window context: %s --> %s\n", old_winpath, winpath);
redraw_only = 1;
new_schematic("switch_no_tcl_ctx", winpath, "");
new_schematic("switch_no_tcl_ctx", winpath, "", 1);
} else {
dbg(1, "callback(): switching window context: %s --> %s, semaphore=%d\n", old_winpath, winpath, xctx->semaphore);
new_schematic("switch", winpath, "");
new_schematic("switch", winpath, "", 1);
}
tclvareval("housekeeping_ctx", NULL);
}
@ -3025,7 +3025,7 @@ int rstate; /* (reduced state, without ShiftMask) */
if(redraw_only) {
xctx->semaphore--; /* decrement articially incremented semaphore (see above) */
dbg(1, "callback(): semaphore >=2 restoring window context: %s <-- %s\n", old_winpath, winpath);
if(old_winpath[0]) new_schematic("switch_no_tcl_ctx", old_winpath, "");
if(old_winpath[0]) new_schematic("switch_no_tcl_ctx", old_winpath, "", 1);
}
else
if(strcmp(old_winpath, winpath)) {

View File

@ -665,9 +665,9 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2 && !strcmp(argv[2], "force")) force = 1;
if(force)
new_schematic("destroy_all", "force", NULL);
new_schematic("destroy_all", "force", NULL, 1);
else
new_schematic("destroy_all", NULL, NULL);
new_schematic("destroy_all", NULL, NULL, 1);
Tcl_SetResult(interp, my_itoa(get_window_count()), TCL_VOLATILE);
}
@ -817,7 +817,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(force || !xctx->modified || !strcmp(tclresult(), "ok")) {
swap_windows();
set_modify(0); /* set modified status to 0 to avoid another confirm in following line */
new_schematic("destroy", xctx->current_win_path, NULL);
new_schematic("destroy", xctx->current_win_path, NULL, 1);
}
} else {
if(!force && xctx->modified) {
@ -844,7 +844,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
if(!has_x || force || !xctx->modified || !strcmp(tclresult(), "ok")) {
swap_tabs();
set_modify(0);
new_schematic("destroy", xctx->current_win_path, NULL);
new_schematic("destroy", xctx->current_win_path, NULL, 1);
}
} else {
if(has_x && !force && xctx->modified) {
@ -860,7 +860,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
} else {
if(force) set_modify(0); /* avoid ask to save downstream */
new_schematic("destroy", xctx->current_win_path, NULL);
new_schematic("destroy", xctx->current_win_path, NULL, 1);
}
Tcl_SetResult(interp, my_itoa(get_window_count()), TCL_VOLATILE);
}
@ -2322,10 +2322,10 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
}
if(!cancel) {
if(f[0]) {
new_schematic("create", "noconfirm", f);
new_schematic("create", "noconfirm", f, 1);
tclvareval("update_recent_file {", f, "}", NULL);
} else {
new_schematic("create", NULL, NULL);
new_schematic("create", NULL, NULL, 1);
}
}
Tcl_ResetResult(interp);
@ -2688,7 +2688,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
Tcl_ResetResult(interp);
}
/* new_schematic create|destroy|destroy_all|switch winpath file
/* new_schematic create|destroy|destroy_all|switch winpath file [draw]
* Open/destroy a new tab or window
* create: create new empty window or with 'file' loaded if 'file' given.
* The winpath must be given (even {} is ok).
@ -2706,18 +2706,20 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
else if(!strcmp(argv[1], "new_schematic"))
{
int r = -1;
int dr = 1;
char s[20];
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2) {
if(argc == 3) r = new_schematic(argv[2], NULL, NULL);
else if(argc == 4) r = new_schematic(argv[2], argv[3], NULL);
else if(argc == 5) {
if(argc >= 6 && argv[5][0] == '0') dr = 0;
if(argc == 3) r = new_schematic(argv[2], NULL, NULL, 1);
else if(argc == 4) r = new_schematic(argv[2], argv[3], NULL, 1);
else if(argc >= 5) {
char f[PATH_MAX + 100];
my_snprintf(f, S(f),"regsub {^~/} {%s} {%s/}", argv[4], home_dir);
tcleval(f);
my_strncpy(f, abs_sym_path(tclresult(), ""), S(f));
r = new_schematic(argv[2], argv[3], f);
r = new_schematic(argv[2], argv[3], f, dr);
}
my_snprintf(s, S(s), "%d", r);
Tcl_SetResult(interp, s, TCL_VOLATILE);
@ -4468,7 +4470,7 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg
{
int r = 1; /* error: no switch was done */
if(!xctx) {Tcl_SetResult(interp, not_avail, TCL_STATIC); return TCL_ERROR;}
if(argc > 2) r = new_schematic("switch", argv[2], NULL);
if(argc > 2) r = new_schematic("switch", argv[2], NULL, 1);
Tcl_SetResult(interp, my_itoa(r), TCL_VOLATILE);
}

View File

@ -83,6 +83,12 @@ Xschem_ctx **get_save_xctx(void)
return save_xctx;
}
/* array of tab names to be matched with xctx->current_win_path
* window_path[0] = .drw
* window_path[1] = .x3.drw
* window_path[2] = .x4.drw
* ...
*/
char *get_window_path(int i)
{
return window_path[i];
@ -864,7 +870,7 @@ static void xwin_exit(void)
tcleval("catch { ngspice::resetdata }"); /* remove ngspice annotation data if any */
/* "1" parameter means to force exit even if there are modified tabs/windows */
if(xctx->infowindow_text) my_free(_ALLOC_ID_, &xctx->infowindow_text);
if(has_x) new_schematic("destroy_all", "1", NULL);
if(has_x) new_schematic("destroy_all", "1", NULL, 1);
delete_schematic_data(1);
if(has_x) {
Tk_DestroyWindow(mainwindow);
@ -1211,10 +1217,11 @@ static int get_tab_or_window_number(const char *win_path)
}
if(n == -1) {
for(i = 0; i < MAX_NEW_WINDOWS; ++i) {
ctx = save_xctx[i];
/* if only one schematic it is not yet saved in save_xctx */
if(get_window_count() == 0 && i == 0) {
ctx = xctx;
} else {
ctx = save_xctx[i];
}
if(ctx && !strcmp(win_path, get_cell_w_ext(ctx->current_name, 0))) {
n = i;
@ -1269,7 +1276,7 @@ void swap_tabs(void)
xctx = ctx;
set_modify(-1);
/* set context to tab that is about to be deleted */
new_schematic("switch_tab", save_xctx[j]->current_win_path, NULL);
new_schematic("switch_tab", save_xctx[j]->current_win_path, NULL, 1);
}
}
@ -1346,7 +1353,7 @@ void swap_windows(void)
/* rebuld colors and pixmaps, redraw swapped schematics */
tclvareval("restore_ctx ", wp_i, NULL);
new_schematic("switch", wp_i, "");
new_schematic("switch", wp_i, "", 1);
tclvareval("housekeeping_ctx", NULL);
tclvareval("xschem build_colors", NULL);
resetwin(1, 1, 1, 0, 0);
@ -1356,7 +1363,7 @@ void swap_windows(void)
/* set context to window that is about to be deleted */
tclvareval("restore_ctx ", wp_j, NULL);
new_schematic("switch", wp_j, "");
new_schematic("switch", wp_j, "", 1);
tclvareval("housekeeping_ctx", NULL);
tclvareval("xschem build_colors", NULL);
resetwin(1, 1, 1, 0, 0);
@ -1368,6 +1375,9 @@ void swap_windows(void)
/* check if filename is already loaded into a tab or window */
/* caller should supply a win_path string for storing matching window path */
/* window_path[0] == ".drw" */
/* window_path[1] == ".x1.drw" */
/* .... */
int check_loaded(const char *f, char *win_path)
{
int i;
@ -1395,11 +1405,13 @@ int check_loaded(const char *f, char *win_path)
return found;
}
/* win_path: .drw for main (first) window, .x1.drw, ... for additional windows */
static int switch_window(int *window_count, const char *win_path, int tcl_ctx)
{
int n;
char my_win_path[80];
Tk_Window tkwin=NULL;
dbg(1, "switch_window(): win_path=%s\n", win_path);
if(xctx->semaphore) return 1; /* some editing operation ongoing. do nothing */
if(!win_path) {
dbg(0, "switch_window(): no filename or window path given\n");
@ -1438,7 +1450,8 @@ static int switch_window(int *window_count, const char *win_path, int tcl_ctx)
return 0;
}
static int switch_tab(int *window_count, const char *win_path)
/* win_path: .drw for main (first) tab, .x1.drw, ... for additional tabs */
static int switch_tab(int *window_count, const char *win_path, int dr)
{
int n;
@ -1464,9 +1477,9 @@ static int switch_tab(int *window_count, const char *win_path)
tclvareval("housekeeping_ctx", NULL);
if(has_x) tclvareval("reconfigure_layers_button {}", NULL);
xctx->window = save_xctx[0]->window;
resetwin(1, 1, 1, 0, 0);
if(dr) resetwin(1, 1, 1, 0, 0);
set_modify(-1); /* sets window title */
draw();
if(dr) draw();
return 0;
} else return 1;
}
@ -1565,7 +1578,7 @@ static void create_new_window(int *window_count, const char *noconfirm, const ch
* because the Expose event after new window creation does a context switch prev win -> new win
*/
tclvareval("restore_ctx ", prev_window, NULL);
new_schematic("switch", prev_window, "");
new_schematic("switch", prev_window, "", 1);
tclvareval("housekeeping_ctx", NULL);
if(has_x) windowid(toppath);
@ -1588,13 +1601,13 @@ static void create_new_tab(int *window_count, const char *noconfirm, const char
if(has_x) {
tcleval(msg);
if(strcmp(tclresult(), "ok")) {
switch_tab(window_count, open_path);
switch_tab(window_count, open_path, 1);
return;
}
}
else {
dbg(0, "create_new_tab: %s already open: %s\n", fname, open_path);
switch_tab(window_count, open_path);
switch_tab(window_count, open_path, 1);
return;
}
}
@ -1631,8 +1644,9 @@ static void create_new_tab(int *window_count, const char *noconfirm, const char
tclvareval(
"button ", ".tabs.x", nn, " -padx 2 -pady 0 -takefocus 0 -anchor nw -text Tab2 "
"-command \"xschem new_schematic switch .x", nn, ".drw\"", NULL);
tclvareval("bind .tabs.x",nn," <ButtonPress> {swap_tabs %X %Y press}", NULL);
tclvareval("bind .tabs.x",nn," <ButtonRelease> {swap_tabs %X %Y release}", NULL);
tclvareval("bind .tabs.x",nn," <ButtonPress-1> {swap_tabs %X %Y press}", NULL);
tclvareval("bind .tabs.x",nn," <ButtonRelease-1> {swap_tabs %X %Y release}", NULL);
tclvareval("bind .tabs.x",nn," <ButtonPress-3> {tab_context_menu %W}", NULL);
tclvareval(
"if {![info exists tctx::tab_bg] } {set tctx::tab_bg [",
".tabs.x", nn, " cget -bg]}", NULL);
@ -1895,7 +1909,7 @@ static void destroy_all_tabs(int *window_count, int force)
* ".drw" ""
* ".x1.drw" ".x1"
*/
int new_schematic(const char *what, const char *win_path, const char *fname)
int new_schematic(const char *what, const char *win_path, const char *fname, int dr)
{
int tabbed_interface;
@ -1922,7 +1936,7 @@ int new_schematic(const char *what, const char *win_path, const char *fname)
destroy_all_tabs(&window_count, (win_path && win_path[0]) ? 1 : 0);
}
} else if(!strcmp(what, "switch")) {
if(tabbed_interface) return switch_tab(&window_count, win_path);
if(tabbed_interface) return switch_tab(&window_count, win_path, dr);
else return switch_window(&window_count, win_path, 1);
} else if(!strcmp(what, "switch_no_tcl_ctx") && !tabbed_interface) {
switch_window(&window_count, win_path, 0);

View File

@ -1634,7 +1634,7 @@ extern void change_layer();
extern void launcher();
extern void windowid(const char *winpath);
extern void preview_window(const char *what, const char *tk_win_path, const char *fname);
extern int new_schematic(const char *what, const char *win_path, const char *fname);
extern int new_schematic(const char *what, const char *win_path, const char *fname, int dr);
extern void toggle_fullscreen(const char *topwin);
extern void toggle_only_probes();
extern int build_colors(double dim, double dim_bg); /* reparse the TCL 'colors' list and reassign colors 20171113 */

View File

@ -5563,6 +5563,150 @@ proc context_menu { } {
return $retval
}
proc tab_ctx_cmd {tab_but what} {
global terminal editor netlist_dir
# get win_path from tab name
set win_path [lindex [$tab_but cget -command] 3] ;# xschem new_schematic switch .x1.drw
set tablist [xschem tab_list]
set found 0
foreach {tabname filename} $tablist {
if {$win_path eq $tabname} {
set found 1
break
}
}
if {!$found} { set filename {}}
if { $filename ne {} } {
if {$what eq {dir}} {
execute 0 xdg-open [file dirname $filename]
} elseif {$what eq {copy}} {
clipboard clear
clipboard append $filename
} elseif {$what eq {term}} {
set save [pwd]
cd [file dirname $filename]
execute 0 $terminal
cd $save
} elseif {$what eq {edit}} {
eval execute 0 $editor $filename
} elseif {$what eq {netlist}} {
set old [xschem get current_win_path]
set save [pwd]
xschem new_schematic switch $win_path {} 0 ;# no draw
cd $netlist_dir
eval execute 0 $editor [xschem get netlist_name fallback]
cd $save
xschem new_schematic switch $old {} 0 ;# no draw
} elseif {$what eq {close}} {
set old [xschem get current_win_path]
xschem new_schematic switch $win_path {} 0 ;# no draw
xschem exit
xschem new_schematic switch $old {} 1 ;# draw
}
}
# puts $filename
}
proc tab_context_menu {tab_but} {
global retval
# find filename associated with tab button
set win_path [lindex [$tab_but cget -command] 3] ;# xschem new_schematic switch .x1.drw
set tablist [xschem tab_list] ;# .drw filename0 .x1.drw filename1 ...
set found 0
foreach {tabname filename} $tablist {
if {$win_path eq $tabname} {
set found 1
break
}
}
if {!$found} { set filename {}}
if {[is_xschem_file $filename] eq {SCHEMATIC}} {
set counterpart [abs_sym_path $filename .sym]
set msg {Open symbol}
} elseif {[is_xschem_file $filename] eq {SYMBOL}} {
set counterpart [abs_sym_path $filename .sch]
set msg {Open schematic}
} else {
set counterpart {}
set msg {}
}
# puts $counterpart
# puts $tab_but
set retval 0
if {[info tclversion] >= 8.5} {
set font {Sans 8 bold}
} else {
set font fixed
}
toplevel .ctxmenu
wm overrideredirect .ctxmenu 1
set x [expr {[winfo pointerx .ctxmenu] - 10}]
set y [expr {[winfo pointery .ctxmenu] - 10}]
button .ctxmenu.b0 -text {Tab menu} -padx 3 -pady 0 -anchor w -activebackground grey50 \
-bg white -highlightthickness 0 -state disabled -disabledforeground black -font [subst $font]
button .ctxmenu.b1 -text {Copy filename} -padx 3 -pady 0 -anchor w -activebackground grey50 \
-highlightthickness 0 -image CtxmenuEdit -compound left \
-font [subst $font] -command "set retval 1; tab_ctx_cmd $tab_but copy; destroy .ctxmenu"
button .ctxmenu.b2 -text {Open directory} -padx 3 -pady 0 -anchor w -activebackground grey50 \
-highlightthickness 0 -image CtxmenuEdit -compound left \
-font [subst $font] -command "set retval 2; tab_ctx_cmd $tab_but dir; destroy .ctxmenu"
button .ctxmenu.b3 -text {Open terminal} -padx 3 -pady 0 -anchor w -activebackground grey50 \
-highlightthickness 0 -image CtxmenuEdit -compound left \
-font [subst $font] -command "set retval 3; tab_ctx_cmd $tab_but term; destroy .ctxmenu"
button .ctxmenu.b4 -text {Edit file} -padx 3 -pady 0 -anchor w -activebackground grey50 \
-highlightthickness 0 -image CtxmenuEdit -compound left \
-font [subst $font] -command "set retval 4; tab_ctx_cmd $tab_but edit; destroy .ctxmenu"
button .ctxmenu.b5 -text {Edit netlist} -padx 3 -pady 0 -anchor w -activebackground grey50 \
-highlightthickness 0 -image CtxmenuEdit -compound left \
-font [subst $font] -command "set retval 5; tab_ctx_cmd $tab_but netlist; destroy .ctxmenu"
if {$counterpart ne {}} {
button .ctxmenu.b6 -text $msg -padx 3 -pady 0 -anchor w -activebackground grey50 \
-highlightthickness 0 -image CtxmenuEdit -compound left \
-font [subst $font] \
-command "
set retval 6
xschem new_schematic create {} $counterpart
destroy .ctxmenu
"
}
button .ctxmenu.b7 -text {Close tab} -padx 3 -pady 0 -anchor w -activebackground grey50 \
-highlightthickness 0 -image CtxmenuEdit -compound left \
-font [subst $font] -command "set retval 7; tab_ctx_cmd $tab_but close; destroy .ctxmenu"
pack .ctxmenu.b0 -fill x -expand true
pack .ctxmenu.b1 -fill x -expand true
pack .ctxmenu.b2 -fill x -expand true
pack .ctxmenu.b3 -fill x -expand true
pack .ctxmenu.b4 -fill x -expand true
pack .ctxmenu.b5 -fill x -expand true
if {$counterpart ne {}} {
pack .ctxmenu.b6 -fill x -expand true
}
pack .ctxmenu.b7 -fill x -expand true
wm geometry .ctxmenu "+$x+$y"
update
# if window has been destroyed (by mouse pointer exiting) do nothing
if { ![winfo exists .ctxmenu] } { return 0 }
set wx [winfo width .ctxmenu]
set wy [winfo height .ctxmenu]
set sx [winfo screenwidth .]
set sy [winfo screenheight .]
if { $y + $wy > $sy } {
set y [expr {$y - ( $y + $wy - $sy )} ]
}
if { $x + $wx > $sx } {
set x [expr {$x - ( $x + $wx - $sx )} ]
}
wm geometry .ctxmenu "+$x+$y";# move away from screen edges
bind .ctxmenu <Leave> {if { {%W} eq {.ctxmenu} } {destroy .ctxmenu}}
tkwait window .ctxmenu
return $retval
}
#
# toolbar: Public variables that we allow to be overridden
# Code contributed by Neil Johnson (github: nejohnson)
@ -5719,8 +5863,9 @@ proc setup_tabbed_interface {} {
frame .tabs
button .tabs.x0 -padx 2 -pady 0 -anchor nw -takefocus 0 \
-text Main -command "xschem new_schematic switch .drw"
bind .tabs.x0 <ButtonPress> {swap_tabs %X %Y press}
bind .tabs.x0 <ButtonRelease> {swap_tabs %X %Y release}
bind .tabs.x0 <ButtonPress-3> {tab_context_menu %W}
bind .tabs.x0 <ButtonPress-1> {swap_tabs %X %Y press}
bind .tabs.x0 <ButtonRelease-1> {swap_tabs %X %Y release}
button .tabs.add -padx 0 -pady 0 -takefocus 0 -text { + } -command "xschem new_schematic create"
pack .tabs.x0 .tabs.add -side left
balloon .tabs.add {Create a new tab}