(**************************************************************************)
(*                                                                        *)
(*  This file is part of Frama-C.                                         *)
(*                                                                        *)
(*  Copyright (C) 2007-2020                                               *)
(*    CEA (Commissariat à l'énergie atomique et aux énergies              *)
(*         alternatives)                                                  *)
(*                                                                        *)
(*  you can redistribute it and/or modify it under the terms of the GNU   *)
(*  Lesser General Public License as published by the Free Software       *)
(*  Foundation, version 2.1.                                              *)
(*                                                                        *)
(*  It 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 Lesser General Public License for more details.                   *)
(*                                                                        *)
(*  See the GNU Lesser General Public License version 2.1                 *)
(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
(*                                                                        *)
(**************************************************************************)

(** The extensible GUI.
    @plugin development guide *)

open Cil_types

(** This is the type of source code buffers that can react to global
    selections and highlighters.
    @since Beryllium-20090901 *)
class type reactive_buffer = object
  inherit Gtk_helper.error_manager
  method buffer : GSourceView.source_buffer
  method locs : Pretty_source.Locs.state
  method rehighlight : unit
  method redisplay : unit
end

(** This class type lists all the methods available to navigate the
    source code through the GUI *)
class type view_code = object

  (** {3 Pretty-printed code} *)

  method scroll : Pretty_source.localizable -> unit
  (** Move the pretty-printed source viewer to the given localizable
      if possible. Return a boolean indicating whether the operation
      succeeded

      @modify Nitrogen-20111001  Now indicates whether the
      operation succeeded. *)

  method display_globals : global list -> unit
  (** Display the given globals in the pretty-printed source viewer. *)


  (** {3 Original code} *)

  method view_original_stmt : stmt -> location
  (** Display the given [stmt] in the original source viewer *)

  method view_original : location -> unit
  (** Display the given location in the original_source_viewer *)


  (** {3 Both pretty-printed and original code} *)

  method view_stmt : stmt -> unit
  (** Display the given [stmt] in the [source_viewer] and in the
      [original_source_viewer]. Equivalent to two successive
      calls to [scroll] and [view_original_stmt]
      @since Carbon-20101201 *)

  method select_or_display_global : global -> unit
  (** This function tries to select the global in the treeview. If
      this fails, for example because the global is not shown in the
      treeview because of filters, it falls back to displaying the
      global by hand.

      @since Nitrogen-20111001 *)
end

class protected_menu_factory:
  Gtk_helper.host -> GMenu.menu -> [ GMenu.menu ] GMenu.factory

(** This is the type of extension points for the GUI.
    @modify Boron-20100401 new way of handling the menu and the toolbar
    @plugin development guide *)
class type main_window_extension_points = object
  inherit view_code

  (** {3 Main Components} *)

  method toplevel : main_window_extension_points
  (** The whole GUI aka self *)

  method menu_manager: unit -> Menu_manager.menu_manager
  (** The object managing the menubar and the toolbar.
      @since Boron-20100401 *)

  method file_tree : Filetree.t
  (** The tree containing the list of files and functions *)

  method file_tree_view : GTree.view
  (** The tree view containing the list of files and functions *)

  method main_window : GWindow.window
  (** The main window *)

  method annot_window : Wtext.text
  (** The information panel.
      The text is automatically cleared whenever the selection is changed.
      You should not directly use the buffer contained in the annot_window
      to add text. Use the method [pretty_information].
  *)
  method pretty_information : 'a. ?scroll:bool -> ('a, Format.formatter, unit) format -> 'a
  (** Pretty print a message in the [annot_window],
      optionally scrolling it to the beginning of the message. *)

  method lower_notebook : GPack.notebook
  (** The lower notebook with messages tabs *)

  (** {4 Source viewers}  *)

  method source_viewer : GSourceView.source_view
  (** The [GText.view] showing the AST. *)

  method source_viewer_scroll : GBin.scrolled_window
  (** The scrolling of the [GText.view] showing the AST. *)

  method reactive_buffer: reactive_buffer
  (** The buffer containing the AST.
      @since Carbon-20101201 *)

  method original_source_viewer : Source_manager.t
  (** The multi-tab source file display widget containing the
      original source. *)


  (** {3 Dialog Boxes} *)

  method launcher : unit -> unit
  (** Display the analysis configuration dialog and offer the
      opportunity to launch to the user *)

  method error :
    'a. ?parent:GWindow.window_skel -> ?reset:bool ->
    ('a, Format.formatter, unit) format -> 'a
  (** Popup a modal dialog displaying an error message. If [reset] is true
      (default is false), the gui is reset after the dialog has been
      displayed. *)

  (** {3 Extension Points} *)

  method register_source_selector :
    (GMenu.menu GMenu.factory
     -> main_window_extension_points
     -> button:int -> Pretty_source.localizable -> unit) -> unit
  (** register an action to perform when button is released on a given
      localizable.
      If the button 3 is released, the first argument is popped as a
      contextual menu. 
      	@plugin development guide *)

  method register_source_highlighter :
    (reactive_buffer -> Pretty_source.localizable ->
     start:int -> stop:int -> unit)
    -> unit
  (** register an highlighting function to run on a given localizable
      between start and stop in the given buffer.
      Priority of [Gtext.tags] is used to decide which tag is rendered on
      top of the other.

      @modify Aluminium-20160501: receives a {!reactive_buffer} instead
      of a {!GSourceView.source_buffer} *)

  method register_panel :
    (main_window_extension_points->(string*GObj.widget*(unit-> unit) option))
    -> unit
  (** [register_panel (name, widget, refresh)] registers a panel in GUI.
      The arguments are the name of the panel to create,
      the widget containing the panel and a function to be called on
      refresh. *)

  (** {3 General features} *)

  method reset : unit -> unit
  (** Reset the GUI and its extensions to its initial state *)

  method rehighlight : unit -> unit
  (** Force to rehighlight the current displayed buffer.
      Plugins should call this method whenever they have changed the states
      on which the function given to [register_source_highlighter] have been
      updated. *)

  method redisplay : unit -> unit
  (** @since Nitrogen-20111001
      Force to redisplay the current displayed buffer.
      Plugins should call this method whenever they have changed the globals.
      For example whenever a plugin adds an annotation, the buffers need
      to be redisplayed. *)

  method protect :
    cancelable:bool -> ?parent:GWindow.window_skel -> (unit -> unit) -> unit
  (** Lock the GUI ; run the function ; catch all exceptions ; Unlock GUI
      The parent window must be set if this method is not called directly
      by the main window: it will ensure that error dialogs are transient
      for the right window.

      Set cancelable to [true] if the protected action should be cancellable
      by the user through button `Stop'. *)

  method full_protect :
    'a . cancelable:bool -> ?parent:GWindow.window_skel -> (unit -> 'a) ->
    'a option
  (** Lock the GUI ; run the function ; catch all exceptions ; Unlock GUI ;
      returns [f ()].
      The parent window must be set if this method is not called directly
      by the main window: it will ensure that error dialogs are transient
      for the right window.

      Set cancelable to [true] if the protected action should be cancellable
      by the user through button `Stop'. *)

  method push_info : 'a. ('a, Format.formatter, unit) format -> 'a
  (** Pretty print a temporary information in the status bar *)

  method pop_info : unit -> unit
  (** Remove last temporary information in the status bar *)

  method show_ids : bool
  (** If [true], the messages shown in the GUI can mention internal ids
      (vid, sid, etc.). If [false], other means of identification should
      be used (line numbers, etc.). *)

  method help_message : 'a 'b.
                             (<event : GObj.event_ops ; .. > as 'a) ->
    ('b, Format.formatter, unit) format ->
    'b
    (** Help message displayed when entering the widget *)

end

class main_window : unit -> main_window_extension_points

val register_extension : (main_window_extension_points -> unit) -> unit
(** Register an extension to the main GUI. It will be invoked at
    initialization time.
    @plugin development guide *)

val register_reset_extension : (main_window_extension_points -> unit) -> unit
(** Register a function to be called whenever the main GUI reset method is
    called. *)

val reactive_buffer : main_window_extension_points ->
  ?parent_window:GWindow.window -> global list -> reactive_buffer
(** This function creates a reactive buffer for the given list of globals.
    These buffers are cached and sensitive to selections and highlighters.
    @since Beryllium-20090901 *)

(** Bullets in left-margins
    @since Nitrogen-20111001 *)
module Feedback :
sig

  val declare_markers: GSourceView.source_view -> unit
  (** Declares the icons used for the property status bullets, as marks in
      the left-margin of the source buffer.
      These icons depend on the GUI theme, and must be reset when the
      theme is changed.
      @since Chlorine-20180501 *)

  val mark : GSourceView.source_buffer
    -> ?call_site:stmt
    -> offset:int
    -> Property_status.Feedback.t -> unit
    (** [offset] is the offset of the character in the source buffer. The
        mark is put in the left-margin of the line corresponding to said
        character. [call_site] is the statement marked, if it is a call. *)

end



(*
Local Variables:
compile-command: "make -C ../../.."
End:
*)
