<commit_before># Copyright (C) 2010-2013 by <NAME> (<EMAIL>)
#
# This file is part of Boxer.
#
#   Boxer 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 3 of the License, or
#   (at your option) any later version.
#
#   Boxer 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 General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with Boxer.  If not, see <http://www.gnu.org/licenses/>.

"""
Here we extend ZoomableArea so that it can show Box pictures, together with
the Boxer reference points and allows the user to insert/move/... them.
"""

import sys

import gtk

from geom2 import square_metric, Point
import document
from zoomable import ZoomableArea, DrawSucceded, DrawFailed
from boxdraw import BoxImageDrawer
from refpoints import GContext, RefPoint, \
  REFPOINT_UNSELECTED, REFPOINT_SELECTED, REFPOINT_DRAGGED
from undoer import Undoer

from config import Configurable


class BoxViewArea(ZoomableArea):
  def __init__(self, filename=None, out_fn=None, callbacks=None, **kwargs):
    # Create the Document
    self.document = d = \
      document.Document(callbacks=callbacks, from_args=kwargs)
    if filename != None:
      d.load_from_file(filename)
    else:
      d.new()

    # Create the Box drawer
    self.drawer = drawer = BoxImageDrawer(d)
    drawer.out_fn = out_fn

    # Create the ZoomableArea
    ZoomableArea.__init__(self, drawer, callbacks=callbacks, **kwargs)

  def get_document(self):
    '''Get the Document object associated to this window.'''
    return self.document


class DraggedPoints(object):
  def __init__(self, points, py_initial_pos):
    self.initial_points = \
      dict((k, v.copy(state=REFPOINT_DRAGGED))
           for k, v in points.iteritems())
    self.py_initial_pos = py_initial_pos


# Functions used by the undoer.
def create_fn(_, editable, name, value):
  editable.refpoint_new(value, name=name, use_py_coords=False, with_cb=False)

def move_fn(_, editable, name, value):
  rp = editable.document.refpoints[name]
  editable.refpoint_move(rp, value, use_py_coords=False)

def delete_fn(_, editable, name):
  editable.refpoint_delete(editable.document.refpoints[name])

def attach_fn(_, editable, child_name, parent_name, index):
  rp_parent = editable.document.refpoints[parent_name]
  rp_child = editable.document.refpoints[child_name]
  editable.refpoint_attach(rp_child, rp_parent, index)

def detach_fn(_, editable, child_name):
  editable.refpoint_detach(editable.document.refpoints[child_name])


class BoxEditableArea(BoxViewArea, Configurable):
  def __init__(self, *args, **kwargs):
    self.undoer = kwargs.pop('undoer', None) or Undoer()

    self._dragged_refpoints = None     # RefPoints which are being dragged
    self._fns = {"refpoint_new": None, # External handler functions
                 "refpoint_delete": None,
                 "refpoint_pick": None,
                 "refpoint_press": None,
                 "refpoint_press_middle": None}

    Configurable.__init__(self, from_args=kwargs)
    BoxViewArea.__init__(self, *args, callbacks=self._fns, **kwargs)

    # Set default configuration
    self.set_config_default(button_left=1, button_center=2, button_right=3,
                            refpoint_size=4, redraw_on_move=True)

    # Enable events and connect signals
    mask = (  gtk.gdk.POINTER_MOTION_MASK
            | gtk.gdk.BUTTON_PRESS_MASK
            | gtk.gdk.BUTTON_RELEASE_MASK)
    self.add_events(mask)
    self.connect("realize", self._realize)
    self.connect("button-press-event", self._on_button_press_event)
    self.connect("motion-notify-event", self._on_motion_notify_event)
    self.connect("button-release-event", self._on_button_release_event)

  def get_refpoints(self, include_dragged=True):
    """Return the refpoints associated to this object (including the dragged
    ones)."""
    for rp in self.document.refpoints:
      yield rp
    if include_dragged and self._dragged_refpoints != None:
      for rp in self._dragged_refpoints.initial_points.itervalues():
        yield rp

  def set_callback(self, name, callback):
    """Set the callbacks."""
    if name not in self._fns:
      raise ValueError("Cannot find '%s'. Available callbacks are: %s."
                       % (name, ", ".join(self._fns.keys())))
    else:
      self._fns[name] = callback

  def _call_back(self, name, *args):
    fn = self._fns.get(name, None)
    if fn != None:
      fn(*args)

  def _realize(self, myself):
    # Set extra default configuration
    unsel_gc = self.window.new_gc()
    unsel_gc.copy(self.style.white_gc)

    sel_gc = self.window.new_gc()
    sel_gc.copy(self.style.white_gc)
    colormap = sel_gc.get_colormap()
    sel_gc.foreground = colormap.alloc_color(gtk.gdk.Color(65535, 65535, 0))

    drag_gc = self.window.new_gc()
    drag_gc.copy(self.style.white_gc)
    colormap = drag_gc.get_colormap()
    drag_gc.foreground = \
      colormap.alloc_color(gtk.gdk.Color(32767, 65535, 32767))

    line_gc = self.window.new_gc()
    line_gc.copy(self.style.black_gc)
    #line_gc.copy(self.style.white_gc)
    #line_gc.set_function(gtk.gdk.XOR)

    self.set_config_default(refpoint_gc=unsel_gc,
                            refpoint_sel_gc=sel_gc,
                            refpoint_drag_gc=drag_gc,
                            refpoint_line_gc=line_gc)

  def refpoint_new(self, coords, name=None, use_py_coords=True, with_cb=True):
    """Add a new reference point whose coordinates are 'point' (a couple
    of floats) and the name is 'name'. If 'name' is not given, then a name
    is generated automatically using the 'base_name' given during construction
    of the class.
    RETURN the name finally chosen for the point.
    """
    screen_view = self.get_visible_coords()
    box_coords = (screen_view.pix_to_coord(coords) if use_py_coords
                  else coords)
    refpoints = self.document.refpoints
    real_name = refpoints.new_name(name)
    if real_name in refpoints:
      raise ValueError("A reference point with the same name exists (%s)"
                       % real_name)

    rp = RefPoint(real_name, box_coords)
    refpoints.append(rp)
    self.repaint_rps(rp)

    self.undoer.begin_group()
    self.undoer.record_action(delete_fn, self, real_name)
    if with_cb:
      self._call_back("refpoint_new", self, rp)
    self.undoer.end_group()<commit_msg>Making lines in direction points rendered using the XOR function. This allows distinguishing the lines on black backgrounds.<commit_after># Copyright (C) 2010-2013 by <NAME> (<EMAIL>)
#
# This file is part of Boxer.
#
#   Boxer 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 3 of the License, or
#   (at your option) any later version.
#
#   Boxer 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 General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with Boxer.  If not, see <http://www.gnu.org/licenses/>.

"""
Here we extend ZoomableArea so that it can show Box pictures, together with
the Boxer reference points and allows the user to insert/move/... them.
"""

import sys

import gtk

from geom2 import square_metric, Point
import document
from zoomable import ZoomableArea, DrawSucceded, DrawFailed
from boxdraw import BoxImageDrawer
from refpoints import GContext, RefPoint, \
  REFPOINT_UNSELECTED, REFPOINT_SELECTED, REFPOINT_DRAGGED
from undoer import Undoer

from config import Configurable


class BoxViewArea(ZoomableArea):
  def __init__(self, filename=None, out_fn=None, callbacks=None, **kwargs):
    # Create the Document
    self.document = d = \
      document.Document(callbacks=callbacks, from_args=kwargs)
    if filename != None:
      d.load_from_file(filename)
    else:
      d.new()

    # Create the Box drawer
    self.drawer = drawer = BoxImageDrawer(d)
    drawer.out_fn = out_fn

    # Create the ZoomableArea
    ZoomableArea.__init__(self, drawer, callbacks=callbacks, **kwargs)

  def get_document(self):
    '''Get the Document object associated to this window.'''
    return self.document


class DraggedPoints(object):
  def __init__(self, points, py_initial_pos):
    self.initial_points = \
      dict((k, v.copy(state=REFPOINT_DRAGGED))
           for k, v in points.iteritems())
    self.py_initial_pos = py_initial_pos


# Functions used by the undoer.
def create_fn(_, editable, name, value):
  editable.refpoint_new(value, name=name, use_py_coords=False, with_cb=False)

def move_fn(_, editable, name, value):
  rp = editable.document.refpoints[name]
  editable.refpoint_move(rp, value, use_py_coords=False)

def delete_fn(_, editable, name):
  editable.refpoint_delete(editable.document.refpoints[name])

def attach_fn(_, editable, child_name, parent_name, index):
  rp_parent = editable.document.refpoints[parent_name]
  rp_child = editable.document.refpoints[child_name]
  editable.refpoint_attach(rp_child, rp_parent, index)

def detach_fn(_, editable, child_name):
  editable.refpoint_detach(editable.document.refpoints[child_name])


class BoxEditableArea(BoxViewArea, Configurable):
  def __init__(self, *args, **kwargs):
    self.undoer = kwargs.pop('undoer', None) or Undoer()

    self._dragged_refpoints = None     # RefPoints which are being dragged
    self._fns = {"refpoint_new": None, # External handler functions
                 "refpoint_delete": None,
                 "refpoint_pick": None,
                 "refpoint_press": None,
                 "refpoint_press_middle": None}

    Configurable.__init__(self, from_args=kwargs)
    BoxViewArea.__init__(self, *args, callbacks=self._fns, **kwargs)

    # Set default configuration
    self.set_config_default(button_left=1, button_center=2, button_right=3,
                            refpoint_size=4, redraw_on_move=True)

    # Enable events and connect signals
    mask = (  gtk.gdk.POINTER_MOTION_MASK
            | gtk.gdk.BUTTON_PRESS_MASK
            | gtk.gdk.BUTTON_RELEASE_MASK)
    self.add_events(mask)
    self.connect("realize", self._realize)
    self.connect("button-press-event", self._on_button_press_event)
    self.connect("motion-notify-event", self._on_motion_notify_event)
    self.connect("button-release-event", self._on_button_release_event)

  def get_refpoints(self, include_dragged=True):
    """Return the refpoints associated to this object (including the dragged
    ones)."""
    for rp in self.document.refpoints:
      yield rp
    if include_dragged and self._dragged_refpoints != None:
      for rp in self._dragged_refpoints.initial_points.itervalues():
        yield rp

  def set_callback(self, name, callback):
    """Set the callbacks."""
    if name not in self._fns:
      raise ValueError("Cannot find '%s'. Available callbacks are: %s."
                       % (name, ", ".join(self._fns.keys())))
    else:
      self._fns[name] = callback

  def _call_back(self, name, *args):
    fn = self._fns.get(name, None)
    if fn != None:
      fn(*args)

  def _realize(self, myself):
    # Set extra default configuration
    unsel_gc = self.window.new_gc()
    unsel_gc.copy(self.style.white_gc)

    sel_gc = self.window.new_gc()
    sel_gc.copy(self.style.white_gc)
    colormap = sel_gc.get_colormap()
    sel_gc.foreground = colormap.alloc_color(gtk.gdk.Color(65535, 65535, 0))

    drag_gc = self.window.new_gc()
    drag_gc.copy(self.style.white_gc)
    colormap = drag_gc.get_colormap()
    drag_gc.foreground = \
      colormap.alloc_color(gtk.gdk.Color(32767, 65535, 32767))

    line_gc = self.window.new_gc()
    line_gc.copy(self.style.white_gc)
    line_gc.set_function(gtk.gdk.XOR)

    self.set_config_default(refpoint_gc=unsel_gc,
                            refpoint_sel_gc=sel_gc,
                            refpoint_drag_gc=drag_gc,
                            refpoint_line_gc=line_gc)

  def refpoint_new(self, coords, name=None, use_py_coords=True, with_cb=True):
    """Add a new reference point whose coordinates are 'point' (a couple
    of floats) and the name is 'name'. If 'name' is not given, then a name
    is generated automatically using the 'base_name' given during construction
    of the class.
    RETURN the name finally chosen for the point.
    """
    screen_view = self.get_visible_coords()
    box_coords = (screen_view.pix_to_coord(coords) if use_py_coords
                  else coords)
    refpoints = self.document.refpoints
    real_name = refpoints.new_name(name)
    if real_name in refpoints:
      raise ValueError("A reference point with the same name exists (%s)"
                       % real_name)

    rp = RefPoint(real_name, box_coords)
    refpoints.append(rp)
    self.repaint_rps(rp)

    self.undoer.begin_group()
    self.undoer.record_action(delete_fn, self, real_name)
    if with_cb:
      self._call_back("refpoint_new", self, rp)
    self.undoer.end_group()
{'fraction_non_alphanumeric': 0.09609497498693348, 'fraction_numerical': 0.005973269618457403, 'mean_word_length': 3.4380384360503644, 'pattern_counts': {'":': 10, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3917257', 'n_tokens_mistral': 4395, 'n_tokens_neox': 4253, 'n_words': 1105}