/*! \brief Closes a page. * \par Function Description * This function closes the page <B>page</B> of toplevel * <B>toplevel</B>. * * If necessary, the current page of <B>toplevel</B> is changed to * the next valid page or to a new untitled page. * * \param [in] w_current The toplevel environment. * \param [in] page The page to close. */ void x_window_close_page (GschemToplevel *w_current, PAGE *page) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); PAGE *new_current = NULL; GList *iter; g_return_if_fail (toplevel != NULL); g_return_if_fail (page != NULL); g_assert (page->pid != -1); /* If we're closing whilst inside an action, re-wind the * page contents back to their state before we started */ if (w_current->inside_action) { i_callback_cancel (w_current, 0, NULL); } if (page == toplevel->page_current) { /* as it will delete current page, select new current page */ /* first look up in page hierarchy */ new_current = s_page_search_by_page_id (toplevel->pages, page->up); if (new_current == NULL) { /* no up in hierarchy, choice is prev, next, new page */ iter = g_list_find( geda_list_get_glist( toplevel->pages ), page ); if ( g_list_previous( iter ) ) { new_current = (PAGE *)g_list_previous( iter )->data; } else if ( g_list_next( iter ) ) { new_current = (PAGE *)g_list_next( iter )->data; } else { /* need to add a new untitled page */ new_current = NULL; } } /* new_current will be the new current page at the end of the function */ } s_log_message (page->CHANGED ? _("Discarding page [%s]\n") : _("Closing [%s]\n"), page->page_filename); /* remove page from toplevel list of page and free */ s_page_delete (toplevel, page); gschem_toplevel_page_changed (w_current); /* Switch to a different page if we just removed the current */ if (toplevel->page_current == NULL) { /* Create a new page if there wasn't another to switch to */ if (new_current == NULL) { new_current = x_window_open_page (w_current, NULL); } /* change to new_current and update display */ x_window_set_current_page (w_current, new_current); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ void x_window_close(GschemToplevel *w_current) { TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current); gboolean last_window = FALSE; /* If we're closing whilst inside an action, re-wind the * page contents back to their state before we started */ if (w_current->inside_action) { i_callback_cancel (w_current, 0, NULL); } /* last chance to save possible unsaved pages */ if (!x_dialog_close_window (w_current)) { /* user somehow cancelled the close */ return; } x_clipboard_finish (w_current); #if DEBUG o_conn_print_hash(w_current->page_current->conn_table); #endif w_current->dont_invalidate = TRUE; /* close all the dialog boxes */ if (w_current->sowindow) gtk_widget_destroy(w_current->sowindow); if (w_current->cswindow) gtk_widget_destroy(w_current->cswindow); if (w_current->tiwindow) gtk_widget_destroy(w_current->tiwindow); if (w_current->tewindow) gtk_widget_destroy(w_current->tewindow); if (w_current->aawindow) gtk_widget_destroy(w_current->aawindow); x_multiattrib_close (w_current); if (w_current->aewindow) gtk_widget_destroy(w_current->aewindow); if (w_current->trwindow) gtk_widget_destroy(w_current->trwindow); x_pagesel_close (w_current); if (w_current->sswindow) gtk_widget_destroy(w_current->sswindow); if (w_current->iwindow) gtk_widget_destroy(w_current->iwindow); if (w_current->hkwindow) gtk_widget_destroy(w_current->hkwindow); if (w_current->cowindow) gtk_widget_destroy(w_current->cowindow); if (w_current->sewindow) gtk_widget_destroy(w_current->sewindow); if (g_list_length (global_window_list) == 1) { /* no more window after this one, remember to quit */ last_window = TRUE; } if (toplevel->major_changed_refdes) { GList* current = toplevel->major_changed_refdes; while (current) { /* printf("yeah freeing: %s\n", (char*) current->data); */ g_free(current->data); current = g_list_next(current); } g_list_free(toplevel->major_changed_refdes); } /* stuff that has to be done before we free w_current */ if (last_window) { /* close the log file */ s_log_close (); /* free the buffers */ o_buffer_free (w_current); } x_window_free_gc(w_current); /* Clear Guile smob weak ref */ if (w_current->smob != SCM_UNDEFINED) { SCM_SET_SMOB_DATA (w_current->smob, NULL); w_current->smob = SCM_UNDEFINED; } /* finally close the main window */ gtk_widget_destroy(w_current->main_window); global_window_list = g_list_remove (global_window_list, w_current); gschem_toplevel_free (w_current); /* just closed last window, so quit */ if (last_window) { gschem_quit(); } }
/*! \todo Finish function documentation!!! * \brief * \par Function Description * */ gint x_event_button_pressed(GschemPageView *page_view, GdkEventButton *event, GschemToplevel *w_current) { PAGE *page = gschem_page_view_get_page (page_view); int w_x, w_y; int unsnapped_wx, unsnapped_wy; g_return_val_if_fail ((w_current != NULL), 0); if (page == NULL) { return TRUE; /* terminate event */ } if (!gtk_widget_has_focus (GTK_WIDGET (page_view))) { gtk_widget_grab_focus (GTK_WIDGET (page_view)); } scm_dynwind_begin ((scm_t_dynwind_flags) 0); g_dynwind_window (w_current); #if DEBUG printf("pressed button %d! \n", event->button); printf("event state: %d \n", event->state); printf("w_current state: %d \n", w_current->event_state); printf("Selection is:\n"); o_selection_print_all(&(page->selection_list)); printf("\n"); #endif gschem_page_view_SCREENtoWORLD (page_view, (int) event->x, (int) event->y, &unsnapped_wx, &unsnapped_wy); w_x = snap_grid (w_current, unsnapped_wx); w_y = snap_grid (w_current, unsnapped_wy); if (event->type == GDK_2BUTTON_PRESS && w_current->event_state == SELECT) { /* Don't re-select an object (lp-912978) */ /* o_find_object(w_current, w_x, w_y, TRUE); */ /* GDK_BUTTON_EVENT is emitted before GDK_2BUTTON_EVENT, which * leads to setting of the inside_action flag. If o_edit() * brings up a modal window (e.g., the edit attribute dialog), * it intercepts the release button event and thus doesn't * allow resetting of the inside_action flag so we do it * manually here before processing the double-click event. */ i_action_stop (w_current); o_edit(w_current, geda_list_get_glist( page->selection_list )); scm_dynwind_end (); return(0); } w_current->SHIFTKEY = (event->state & GDK_SHIFT_MASK ) ? 1 : 0; w_current->CONTROLKEY = (event->state & GDK_CONTROL_MASK) ? 1 : 0; w_current->ALTKEY = (event->state & GDK_MOD1_MASK) ? 1 : 0; /* Huge switch statement to evaluate state transitions. Jump to * end_button_pressed label to escape the state evaluation rather than * returning from the function directly. */ if (event->button == 1) { if (w_current->inside_action) { /* End action */ if (page->place_list != NULL) { switch(w_current->event_state) { case (COMPMODE) : o_place_end(w_current, w_x, w_y, w_current->continue_component_place, "%add-objects-hook"); break; case (TEXTMODE) : o_place_end(w_current, w_x, w_y, FALSE, "%add-objects-hook"); break; case (PASTEMODE) : o_place_end(w_current, w_x, w_y, FALSE, "%paste-objects-hook"); break; default: break; } } else { switch(w_current->event_state) { case (ARCMODE) : o_arc_end1(w_current, w_x, w_y); break; case (BOXMODE) : o_box_end(w_current, w_x, w_y); break; case (BUSMODE) : o_bus_end(w_current, w_x, w_y); break; case (CIRCLEMODE) : o_circle_end(w_current, w_x, w_y); break; case (LINEMODE) : o_line_end(w_current, w_x, w_y); break; case (NETMODE) : o_net_end(w_current, w_x, w_y); break; case (PATHMODE) : o_path_continue (w_current, w_x, w_y); break; case (PICTUREMODE): o_picture_end(w_current, w_x, w_y); break; case (PINMODE) : o_pin_end (w_current, w_x, w_y); break; default: break; } } } else { /* Start action */ switch(w_current->event_state) { case (ARCMODE) : o_arc_start(w_current, w_x, w_y); break; case (BOXMODE) : o_box_start(w_current, w_x, w_y); break; case (BUSMODE) : o_bus_start(w_current, w_x, w_y); break; case (CIRCLEMODE) : o_circle_start(w_current, w_x, w_y); break; case (LINEMODE) : o_line_start(w_current, w_x, w_y); break; case (NETMODE) : o_net_start(w_current, w_x, w_y); break; case (PATHMODE) : o_path_start (w_current, w_x, w_y); break; case (PICTUREMODE): o_picture_start(w_current, w_x, w_y); break; case (PINMODE) : o_pin_start (w_current, w_x, w_y); break; case (ZOOMBOX) : a_zoom_box_start(w_current, unsnapped_wx, unsnapped_wy); break; case (SELECT) : o_select_start(w_current, w_x, w_y); break; case (COPYMODE) : case (MCOPYMODE) : o_copy_start(w_current, w_x, w_y); break; case (MOVEMODE) : o_move_start(w_current, w_x, w_y); break; default: break; } } switch(w_current->event_state) { case(ROTATEMODE): o_rotate_world_update(w_current, w_x, w_y, 90, geda_list_get_glist(page->selection_list)); break; case(MIRRORMODE): o_mirror_world_update(w_current, w_x, w_y, geda_list_get_glist(page->selection_list)); break; case(PAN): gschem_page_view_pan (page_view, w_x, w_y); i_set_state(w_current, SELECT); break; } } else if (event->button == 2) { /* try this out and see how it behaves */ if (w_current->inside_action) { if (!(w_current->event_state == COMPMODE|| w_current->event_state == TEXTMODE|| w_current->event_state == MOVEMODE|| w_current->event_state == COPYMODE || w_current->event_state == MCOPYMODE || w_current->event_state == PASTEMODE )) { i_callback_cancel(w_current, 0, NULL); } goto end_button_pressed; } switch(w_current->middle_button) { case(ACTION): /* don't want to search if shift */ /* key is pressed */ if (!w_current->SHIFTKEY) { o_find_object(w_current, unsnapped_wx, unsnapped_wy, TRUE); } /* make sure the list is not empty */ if (!o_select_selected(w_current)) { /* this means the above find did not * find anything */ i_action_stop (w_current); i_set_state(w_current, SELECT); goto end_button_pressed; } /* determine here if copy or move */ if (w_current->ALTKEY) { i_set_state(w_current, COPYMODE); o_copy_start(w_current, w_x, w_y); } else { o_move_start(w_current, w_x, w_y); } break; case(REPEAT): if (w_current->last_callback != NULL) { (*w_current->last_callback)(w_current, 0, NULL); } break; #ifdef HAVE_LIBSTROKE case(STROKE): DOING_STROKE=TRUE; break; #endif /* HAVE_LIBSTROKE */ case(MID_MOUSEPAN_ENABLED): gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y); break; } } else if (event->button == 3) { if (!w_current->inside_action) { if (w_current->third_button == POPUP_ENABLED) { /* (third-button "popup") */ i_update_menus(w_current); /* update menus before popup */ do_popup(w_current, event); } else { /* (third-button "mousepan") */ gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y); } } else { if ((w_current->third_button == MOUSEPAN_ENABLED) && (!w_current->third_button_cancel)) { gschem_page_view_pan_start (page_view, (int) event->x, (int) event->y); } else { /* this is the default cancel */ /* reset all draw and place actions */ switch (w_current->event_state) { case (ARCMODE) : o_arc_invalidate_rubber (w_current); break; case (BOXMODE) : o_box_invalidate_rubber (w_current); break; case (BUSMODE) : o_bus_invalidate_rubber (w_current); break; case (CIRCLEMODE) : o_circle_invalidate_rubber (w_current); break; case (LINEMODE) : o_line_invalidate_rubber (w_current); break; case (NETMODE) : o_net_reset (w_current); break; case (PATHMODE) : o_path_invalidate_rubber (w_current); break; case (PICTUREMODE): o_picture_invalidate_rubber (w_current); break; case (PINMODE) : o_pin_invalidate_rubber (w_current); break; default: i_callback_cancel(w_current, 0, NULL); break; } } } } end_button_pressed: scm_dynwind_end (); return(0); }