# menu.py
#
# Moleskine: a source code editor for the GNOME desktop
#
# Copyright (c) 2000 - 2002   Michele Campeotto <micampe@micampe.it>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

import os

import gnome.ui
from gnome.uiconsts import *
import GDK

import GTKSCINTILLA

import Moleskine
import Dialogs
import CVS

MENU_SETTINGS = _('_Settings')
MENU_CHANGE_LANGUAGE = _('Change _language')
MENU_FILE = _('_File')
MENU_OPEN_PREVIOUS = _('Open pre_vious')
MENU_MRU = MENU_FILE + '/' + MENU_OPEN_PREVIOUS + '/'
MENU_RECENT_SESSIONS = _('Recent sessions')
MENU_RSESS = MENU_FILE + '/' + MENU_RECENT_SESSIONS + '/'

fullscreen = 0

def new_document(w, user_data=None):
    Moleskine.app.new_document()

def open_document(w, user_data=None):
    def ok_clicked(fs, user_data=None):
        filename = fs.get_filename()
        selection = fs.file_list.selection
        if len(selection) > 0:
            dir = os.path.dirname(filename)
            for item in selection:
                file = os.path.join(dir, fs.file_list.get_text(item, 0))
                Moleskine.app.open_document(file)
        else:
            Moleskine.app.open_document(filename)
    Moleskine.app.ask_file(type = 'load', ok_cb = ok_clicked)

# FIXME: This function is *ugly*, but user_data is always None and
# I don't know how to get the label of a GtkRadioMenuItem :(
def open_recent(w, user_data=None):
    from gtk import GtkMenuItem, GtkMenu
    import copy
    
    item = GtkMenuItem(_obj = w)
    menu = item.get_ancestor(GtkMenu.get_type())
    app = Moleskine.app
    temp_list = copy.copy(app.files)
    if int(app.prefs['history/mru_sort']):
        temp_list.sort()
    menu_items = menu.children()
    if len(temp_list) < len(menu_items):
        menu_items = menu_items[1:]
    Moleskine.app.open_document(temp_list[menu_items.index(item)])
    
    del GtkMenuItem, GtkMenu

def open_recent_session(w, user_data=None):
    from gtk import GtkMenuItem, GtkMenu
    import copy
    
    item = GtkMenuItem(_obj = w)
    menu = item.get_ancestor(GtkMenu.get_type())
    app = Moleskine.app
    temp_list = copy.copy(app.rsessions)
    menu_items = menu.children()
    if len(temp_list) < len(menu_items):
        menu_items = menu_items[1:]
    Moleskine.app.load_session(temp_list[menu_items.index(item)])
    
    del GtkMenuItem, GtkMenu

def clean_up_mru(w, user_data=None):
    Moleskine.app.clean_up_mru()

def delete_mru(w, user_data=None):
    Moleskine.app.delete_mru()

def save_document(w, user_data=None):
    app = Moleskine.app
    if app.get_current_document().filepath is None:
        save_as_document(w)
    else:
        app.save_document()

def save_as_document(w, user_data=None):
    def ok_clicked(fs, user_data=None):
        Moleskine.app.save_document(fs.get_filename())
    app = Moleskine.app
    app.ask_file(type = 'save', ok_cb = ok_clicked)

def save_all(w, user_data=None):
    for doc in Moleskine.app.documents:
        doc.save_file()

def revert_document(w, user_data=None):
    Moleskine.app.get_current_document().revert()

def load_session(w, user_data=None):
    def ok_clicked(fs, user_data=None):
        filename = fs.get_filename()
        if not os.path.exists(filename) or not os.access(filename, os.R_OK):
            gnome.ui.GnomeMessageBox(
                _('File not found: %s') % filename,
                gnome.uiconsts.MESSAGE_BOX_ERROR,
                gnome.uiconsts.STOCK_BUTTON_OK).run_and_close()
        else:
            Moleskine.app.load_session(filename)
    Moleskine.app.ask_file(type = 'load_session', ok_cb = ok_clicked)

def save_session(w, user_data=None):
    def ok_clicked(fs, user_data=None):
        filename = fs.get_filename()
        file_ok = 0
        if not os.access(filename, os.F_OK):
            if os.access(os.path.dirname(filename), os.W_OK):
                file_ok = 1
        else:
            if os.access(filename, os.W_OK):
                file_ok = 1
        if not file_ok:
            gnome.ui.GnomeMessageBox(
                _('File can not be written: %s\n\nPermission denied.') % filename,
                gnome.uiconsts.MESSAGE_BOX_ERROR,
                gnome.uiconsts.STOCK_BUTTON_OK).run_and_close()
        else:
            Moleskine.app.save_session(filename)
    Moleskine.app.ask_file(type = 'save_session', ok_cb = ok_clicked)

def file_next(w, user_data=None):
    app = Moleskine.app
    if app.notebook.get_current_page() == len(app.documents) - 1:
        app.notebook.set_page(0)
    else:
        app.notebook.next_page()

def file_previous(w, user_data=None):
    app = Moleskine.app
    if app.notebook.get_current_page() == 0:
        app.notebook.set_page(-1)
    else:
        app.notebook.prev_page()

def file_last_used(w, user_data=None):
    app = Moleskine.app
    app.notebook.set_page(app.last_page[1])

def close_document(w, user_data=None):
    Moleskine.app.close_document()

def close_all(w, user_data=None):
    Moleskine.app.notebook.set_page(0)
    for i in range(len(Moleskine.app.documents)):
        Moleskine.app.close_document()

def exit(w, user_data=None):
    from gtk import mainquit
    from gnome.ui import GnomeMessageBox
    
    unsaved = 0
    for doc in Moleskine.app.documents:
        if not doc.can_close():
            unsaved = 1
            break
    res = 0
    if unsaved:
        res = GnomeMessageBox(
                _('There are unsaved files.\nDo you want to exit anyway?'),
                MESSAGE_BOX_QUESTION,
                STOCK_BUTTON_YES, STOCK_BUTTON_NO).run_and_close()
    if res == 0:
        Moleskine.app.save_prefs()
        Moleskine.app.save_mru()
        Moleskine.app.save_session()
        Moleskine.app.save_rsess()
        mainquit()
    else:
        return 1

def undo(w, user_data=None):
    Moleskine.app.get_current_document().undo()

def redo(w, user_data=None):
    Moleskine.app.get_current_document().redo()

def cut(w, user_data=None):
    Moleskine.app.get_current_document().cut()

def copy(w, user_data=None):
    Moleskine.app.get_current_document().copy()

def paste(w, user_data=None):
    Moleskine.app.get_current_document().paste()

def search(w, user_data=None):
    Dialogs.search()

def search_in_files(w, user_data=None):
    Dialogs.search_in_files()

def search_next(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    if doc.search_next():
        doc.ensure_visible(doc.line_from_position(doc.get_selection_start()))

def search_previous(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    if doc.search_previous():
        doc.ensure_visible(doc.line_from_position(doc.get_selection_start()))

def replace(w, user_data=None):
    Dialogs.replace()

def goto_line(w, user_data=None):
    def clicked(line, user_data=None):
        if line is not None:
            Moleskine.app.get_current_document().goto_line(int(line) - 1)
    gnome.ui.GnomeRequestDialog(0, _('Line number:'), '', 7, clicked, Moleskine.app).run_and_close()

def replace_next(w, user_data=None):
    pass

def complete_word(w, user_data=None):
    Moleskine.app.get_current_document().complete_word()

def options(w, user_data=None):
    Dialogs.options()

def lang_settings(w, user_data=None):
    Dialogs.languages()

# FIXME: This function is *ugly*, but user_data is always None and
# I don't know how to get the label of a GtkRadioMenuItem :(
def set_lang(w, user_data=None):
    from gtk import GtkRadioMenuItem, GtkMenu
    
    item = GtkRadioMenuItem(_obj = w)
    if not item.active:
        return
    menu = item.get_ancestor(GtkMenu.get_type())
    app = Moleskine.app
    doc = app.get_current_document()
    langs_names = app.langs.keys()
    langs_names.sort()
    menu_items = menu.children()
    if len(langs_names) < len(menu_items):
        menu_items = menu_items[1:]
    doc.set_language(app.langs[langs_names[menu_items.index(item)]])
    
    app.langs_menu = menu
    
    del GtkRadioMenuItem, GtkMenu

def toggle_ws(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    show = not doc.get_view_ws()
    doc.set_view_ws(show)
    Moleskine.app.prefs['view/ws'] = show

def toggle_eol(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    show = not doc.get_view_eol()
    doc.set_view_eol(show)
    Moleskine.app.prefs['view/eol'] = show

def toggle_wrap(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    wrap = not doc.get_wrap_mode()
    doc.set_wrap_mode(wrap)
    doc.set_h_scroll_bar(not wrap)
    Moleskine.app.prefs['view/wrap'] = wrap

def eol_to_lf(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    doc.set_eol_mode(GTKSCINTILLA.EOL_LF)
    doc.convert_eols(GTKSCINTILLA.EOL_LF)

def eol_to_cr(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    doc.set_eol_mode(GTKSCINTILLA.EOL_CR)
    doc.convert_eols(GTKSCINTILLA.EOL_CR)

def eol_to_crlf(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    doc.set_eol_mode(GTKSCINTILLA.EOL_CRLF)
    doc.convert_eols(GTKSCINTILLA.EOL_CRLF)

def next_bookmark(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    line = doc.get_current_line()
    new_line = doc.marker_next(line + 1, 2)
    if new_line < 0:
        new_line = doc.marker_next(0, 2)
    if new_line >= 0:
        doc.goto_line(new_line)
        cur_scroll_pos = doc.get_first_visible_line()
        cur_top = doc.visible_from_doc_line(cur_scroll_pos)
        line_top = doc.visible_from_doc_line(new_line - 1)
        doc.line_scroll(0, line_top - cur_top)

def prev_bookmark(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    line = doc.get_current_line()
    new_line = doc.marker_previous(line - 1, 2)
    if new_line < 0:
        new_line = doc.marker_previous(doc.get_line_count(), 2)
    if new_line >= 0:
        doc.goto_line(new_line)
        cur_scroll_pos = doc.get_first_visible_line()
        cur_top = doc.visible_from_doc_line(cur_scroll_pos)
        line_top = doc.visible_from_doc_line(new_line - 1)
        doc.line_scroll(0, line_top - cur_top)

def toggle_bookmark(w, user_data=None):
    doc = Moleskine.app.get_current_document()
    line = doc.get_current_line()
    if doc.marker_get(line) > 0:
        doc.marker_delete(line, 1)
    else:
        doc.marker_add(line, 1)

def clear_bookmarks(w, user_data=None):
    Moleskine.app.get_current_document().marker_delete_all(1)

def cvs_commit(w, user_data=None):
    CVS.CVS('commit')

def cvs_update(w, user_data=None):
    CVS.CVS('update')

def cvs_status(w, user_data=None):
    CVS.CVS('status')

def cvs_log(w, user_data=None):
    CVS.CVS('log')

def cvs_add(w, user_data=None):
    CVS.CVS('add')

def cvs_remove(w, user_data=None):
    CVS.CVS('remove')

def cvs_diff(w, user_data=None):
    CVS.CVS('diff')

def cvs_commit_dir(w, user_data=None):
    CVS.CVS('commit', 1)

def cvs_update_dir(w, user_data=None):
    CVS.CVS('update', 1)

def cvs_diff_dir(w, user_data=None):
    CVS.CVS('diff', 1)

def cvs_status_dir(w, user_data=None):
    CVS.CVS('status', 1)

def cvs_log_dir(w, user_data=None):
    CVS.CVS('log', 1)

def cvs_add_dir(w, user_data=None):
    CVS.CVS('add', 1)

def about(w, user_data=None):
    from about import show_infos
    show_infos()


file_menu = [
    (APP_UI_ITEM, _('_New'), _('Create a new file'),
     new_document, None, APP_PIXMAP_STOCK, STOCK_MENU_NEW,
     GDK.n, GDK.CONTROL_MASK),
    (APP_UI_ITEM, _('_Open...'), _('Load a file from disk'),
     open_document, None, APP_PIXMAP_STOCK, STOCK_MENU_OPEN,
     GDK.o, GDK.CONTROL_MASK),
    UIINFO_SUBTREE_STOCK(MENU_OPEN_PREVIOUS, [], STOCK_MENU_BOOK_OPEN),
    UIINFO_SEPARATOR,
    UIINFO_MENU_SAVE_ITEM(save_document),
    (APP_UI_ITEM, _('Save _As...'), _('Save the file to a different name'),
     save_as_document, None, APP_PIXMAP_STOCK, STOCK_MENU_SAVE_AS,
     GDK.s, GDK.CONTROL_MASK + GDK.SHIFT_MASK),
    (APP_UI_ITEM, _('Save all'), _('Save all open files'),
     save_as_document, None, APP_PIXMAP_STOCK, STOCK_MENU_SAVE,
     GDK.s, GDK.CONTROL_MASK + GDK.MOD1_MASK),
    (APP_UI_ITEM, _('_Revert'), _('Reload the last saved version of the current file'),
     revert_document, None, APP_PIXMAP_STOCK, STOCK_MENU_REVERT,
     GDK.i, GDK.CONTROL_MASK),
    UIINFO_SEPARATOR,
    (APP_UI_ITEM, _('Load session...'), _('Load session from a file'),
     load_session, None, APP_PIXMAP_STOCK, STOCK_MENU_TIMER, GDK.F11, 0),
    (APP_UI_ITEM, _('Save session...'), _('Save current session to a file'),
     save_session, None, APP_PIXMAP_STOCK, STOCK_MENU_TIMER_STOP, GDK.F12, 0),
    UIINFO_SUBTREE_STOCK(MENU_RECENT_SESSIONS, [], STOCK_MENU_BOOK_OPEN),
    UIINFO_SEPARATOR,
    (APP_UI_ITEM, _('Next'), None, file_next, None,
     APP_PIXMAP_STOCK, STOCK_MENU_FORWARD, GDK.period, GDK.CONTROL_MASK),
    (APP_UI_ITEM, _('Previous'), None, file_previous, None,
     APP_PIXMAP_STOCK, STOCK_MENU_BACK, GDK.comma, GDK.CONTROL_MASK),
    (APP_UI_ITEM, _('Last used'), None, file_last_used, None,
     APP_PIXMAP_NONE, None, GDK.P, GDK.CONTROL_MASK),
    UIINFO_SEPARATOR,
    UIINFO_MENU_CLOSE_ITEM(close_document),
    (APP_UI_ITEM, _('Close all'), None, close_all, None,
     APP_PIXMAP_STOCK, STOCK_MENU_CLOSE,
     GDK.w, GDK.CONTROL_MASK + GDK.MOD1_MASK),
    UIINFO_MENU_EXIT_ITEM(exit)
]

edit_menu = [
    UIINFO_MENU_UNDO_ITEM(undo),
    (APP_UI_ITEM, _('_Redo'), _('Redo last action'),
     redo, None, APP_PIXMAP_STOCK, STOCK_MENU_REDO,
     GDK.z, GDK.CONTROL_MASK + GDK.SHIFT_MASK),
    UIINFO_SEPARATOR,
    UIINFO_MENU_CUT_ITEM(cut),
    UIINFO_MENU_COPY_ITEM(copy),
    UIINFO_MENU_PASTE_ITEM(paste),
    UIINFO_SEPARATOR,
    (APP_UI_ITEM, _('_Search...'), _('Search a string in current file'),
     search, None, APP_PIXMAP_STOCK, STOCK_MENU_SEARCH,
     GDK.f, GDK.CONTROL_MASK),
    (APP_UI_ITEM, _('Search in _files...'), _('Search a string in multiple files'),
     search_in_files, None, APP_PIXMAP_STOCK, STOCK_MENU_SEARCH,
     0, 0),
    (APP_UI_ITEM, _('Search _Next'), _('Search the next occurrence of the last searched string'),
     search_next, None, APP_PIXMAP_STOCK, STOCK_MENU_SEARCH,
     GDK.g, GDK.CONTROL_MASK),
    (APP_UI_ITEM, _('Search _Previous'), _('Search the previous occurrence of the last searched string'),
     search_previous, None, APP_PIXMAP_STOCK, STOCK_MENU_SEARCH,
     GDK.g, GDK.CONTROL_MASK + GDK.SHIFT_MASK),
#    UIINFO_SEPARATOR,
    (APP_UI_ITEM, _('_Replace...'), _('Search and replace a string in the current file'),
     replace, None, APP_PIXMAP_STOCK, STOCK_MENU_SRCHRPL,
     GDK.r, GDK.CONTROL_MASK),
#    (APP_UI_ITEM, 'Replace Next',
#     'Search and replace next string in current file',
#     replace_next, None, APP_PIXMAP_STOCK, STOCK_MENU_SRCHRPL,
#     GDK.e, GDK.CONTROL_MASK),
    UIINFO_SEPARATOR,
    (APP_UI_ITEM, _('_Goto line...'), _('Go to specified line in current file'),
     goto_line, None, APP_PIXMAP_STOCK, STOCK_MENU_JUMP_TO,
     GDK.l, GDK.CONTROL_MASK + GDK.MOD1_MASK),
]

settings_menu = [
    UIINFO_ITEM_STOCK(_('_Configuration'), None, options, STOCK_MENU_PROP),
    UIINFO_SEPARATOR,
    UIINFO_ITEM_STOCK(_('Languages _settings...'), None,
                      lang_settings, STOCK_MENU_PREF),
    UIINFO_SUBTREE_STOCK(MENU_CHANGE_LANGUAGE, [], STOCK_MENU_JUMP_TO),
    UIINFO_SEPARATOR,
    (APP_UI_TOGGLEITEM, _('Show _white space'), None, toggle_ws, None,
     APP_PIXMAP_NONE, None, GDK.w, GDK.CONTROL_MASK + GDK.MOD1_MASK),
    (APP_UI_TOGGLEITEM, _('Show _end of line'), None, toggle_eol, None,
     APP_PIXMAP_NONE, None, GDK.s, GDK.CONTROL_MASK + GDK.MOD1_MASK),
    (APP_UI_TOGGLEITEM, _('Word wra_p'), None, toggle_wrap, None,
     APP_PIXMAP_NONE, None, GDK.p, GDK.CONTROL_MASK + GDK.MOD1_MASK),
]

tools_menu = [
    (APP_UI_ITEM, _('_Next bookmark'), None, next_bookmark, None,
     APP_PIXMAP_STOCK, STOCK_MENU_FORWARD, GDK.b, GDK.CONTROL_MASK),
    (APP_UI_ITEM, _('_Previous bookmark'), None, prev_bookmark, None,
     APP_PIXMAP_STOCK, STOCK_MENU_BACK,
     GDK.b, GDK.CONTROL_MASK + GDK.SHIFT_MASK),
    (APP_UI_ITEM, _('_Toggle bookmark'), None, toggle_bookmark, None,
     APP_PIXMAP_STOCK, STOCK_MENU_BOOK_YELLOW, GDK.b, GDK.MOD1_MASK),
    UIINFO_ITEM_STOCK(_('_Clear bookmarks'), None,
                      clear_bookmarks, STOCK_MENU_TRASH_FULL),
    UIINFO_SEPARATOR,
    (APP_UI_ITEM, _('_Complete word'),
     '',
     complete_word, None, APP_PIXMAP_STOCK, STOCK_MENU_JUMP_TO,
     GDK.space, GDK.CONTROL_MASK),
    UIINFO_SEPARATOR,
    UIINFO_SUBTREE(_('Convert _EOLs'), [
        UIINFO_ITEM(_('LF (_Unix)'), None, eol_to_lf),
        UIINFO_ITEM(_('CR (_Mac)'), None, eol_to_cr),
        UIINFO_ITEM(_('CR+LF (Dos/_Win)'), None, eol_to_crlf)]),
    UIINFO_SEPARATOR,
    UIINFO_SUBTREE(_('CVS'), [
        UIINFO_ITEM(_('Commit file to CVS'), None, cvs_commit),
        UIINFO_ITEM(_('Update file from CVS'), None, cvs_update),
        UIINFO_ITEM(_('CVS diff file'), None, cvs_diff),
        UIINFO_ITEM(_('File\'s CVS status'), None, cvs_status),
        UIINFO_ITEM(_('File\'s CVS log'), None, cvs_log),
        UIINFO_ITEM(_('Add file to CVS'), None, cvs_add),
        UIINFO_ITEM(_('Remove file from CVS'), None, cvs_remove),
        UIINFO_SEPARATOR,
        UIINFO_ITEM(_('Commit directory to CVS'), None, cvs_commit_dir),
        UIINFO_ITEM(_('Update directory from CVS'), None, cvs_update_dir),
        UIINFO_ITEM(_('CVS diff directory'), None, cvs_diff_dir),
        UIINFO_ITEM(_('Directory\'s CVS status'), None, cvs_status_dir),
        UIINFO_ITEM(_('Directory\'s CVS log'), None, cvs_log_dir),
        UIINFO_ITEM(_('Add directory to CVS'), None, cvs_add_dir)#,
        #UIINFO_ITEM(_('Remove directory from CVS'), None, cvs_directory)
        ]),
    UIINFO_SEPARATOR,
    (APP_UI_ITEM, _('Clean-up recent files list'), None, clean_up_mru, None,
     APP_PIXMAP_NONE, None, 0, 0),
    (APP_UI_ITEM, _('Delete recent files list'), None, delete_mru, None,
     APP_PIXMAP_NONE, None, 0, 0),
]

help_menu = [
# There is a problem with Ximian GNOME 1.4 (doorman) and `About' menu items...
#    UIINFO_MENU_ABOUT_ITEM(about)
    UIINFO_ITEM_STOCK(_('Moleskine info'), None, about, STOCK_MENU_ABOUT)
]

main_menu = [
    UIINFO_SUBTREE(MENU_FILE, file_menu),
    UIINFO_SUBTREE(_('_Edit'), edit_menu),
    UIINFO_SUBTREE(MENU_SETTINGS, settings_menu),
    UIINFO_SUBTREE(_('_Tools'), tools_menu),
    UIINFO_SUBTREE(_('_Help'), help_menu)
]
