/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A typical XPCE/Prolog module header. Always make sure to load module library(pce) explicitly if you want to write modules portable to the various Prolog dialects supported by XPCE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ :- module(wysiwyg, [ wysiwyg/1 % +File ]). :- use_module(library(pce)). :- use_module(library(pce_style_item)). :- use_module(library(pce_report)). /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create the main window, consisting of a frame holding a dialog window with a button for defining new styles and a menu for setting the style of the selection. Both dialog items use call-back to @prolog. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ wysiwyg(File) :- new(Fr, frame(File)), send(Fr, append, new(D, dialog)), send(new(V, view), below, D), send(new(report_dialog), below, V), send(V, font, normal), send(D, append, button(define_style, message(@prolog, define_style, Fr))), send(D, append, menu(style, toggle, and(message(@prolog, set_style, Fr, @arg1), message(@receiver, clear_selection))), right), append_style(Fr, bold, style(font := bold)), append_style(Fr, italic, style(font := italic)), send(V, load, File), send(Fr, open). /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Set the style for the current selection. Simply pick the selection start and end and make a fragment using the selection parameters and the style-name. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ set_style(Fr, Style) :- get(Fr, member, view, V), get(V, selection, point(Start, End)), ( get(V, mark_status, active) -> get(V, text_buffer, TB), new(_, fragment(TB, Start, End-Start, Style)) ; send(Fr, report, warning, 'No selection') ). /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Define a new style and add it to the menu and the view. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ define_style(Fr) :- ask_style(Fr, Name, Style), append_style(Fr, Name, Style). append_style(Fr, Name, Style) :- get(Fr, member, dialog, D), get(D, member, style, Menu), send(Menu, append, Name), send(Menu, active, @on), get(Fr, member, view, View), send(View, style, Name, Style). /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Prompt for the style-name and style-object. Class style_item is defined in the library(pce_style_item). `frame ->transient_for' tells the window manager the dialog is a supporting frame for the main application. `frame <-confirm_centered' opens the frame centered around the given location and starts processing events until `frame->return' is activated. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ask_style(Fr, Name, Style) :- new(D, dialog('Define Style')), send(D, append, new(N, text_item(name, ''))), send(D, append, new(S, style_item(style))), send(D, append, button(ok, message(D, return, ok))), send(D, append, button(cancel, message(D, return, cancel))), send(D, default_button, ok), send(D, transient_for, Fr), repeat, get(D, confirm_centered, Fr?area?center, Answer), ( Answer == ok -> get(N, selection, Name), ( Name == '' -> send(D, report, error, 'Please enter a name'), fail ; !, get(S, selection, Style), send(Style, lock_object, @on), send(D, destroy) ) ; !, send(D, destroy), fail ).