# GNU Enterprise Forms - GF Object Hierarchy - Logical Page
#
# Copyright 2001-2009 Free Software Foundation
#
# This file is part of GNU Enterprise
#
# GNU Enterprise 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, or (at your option) any later version.
#
# GNU Enterprise 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 program; see the file COPYING. If not,
# write to the Free Software Foundation, Inc., 59 Temple Place
# - Suite 330, Boston, MA 02111-1307, USA.
#
# $Id: GFPage.py 9956 2009-10-11 18:54:57Z reinhard $
"""
Logical page support
"""

from gnue.forms.GFObjects.GFContainer import GFContainer

__all__ = ['GFPage']


# =============================================================================
# Implementation of a logical page object
# =============================================================================

class GFPage(GFContainer):
    """
    Implementation of the <page> tag
    """

    # -------------------------------------------------------------------------
    # Attributes
    # -------------------------------------------------------------------------

    name = None
    transparent = False
    style = 'normal'
    caption = None


    # -------------------------------------------------------------------------
    # Constructor
    # -------------------------------------------------------------------------

    def __init__(self, parent=None):

        GFContainer.__init__(self, parent, "GFPage")

        self._validTriggers = {
            'PRE-FOCUSOUT' : 'Pre-FocusOut',
            'POST-FOCUSOUT': 'Post-FocusOut',
            'PRE-FOCUSIN'  : 'Pre-FocusIn',
            'POST-FOCUSIN' : 'Post-FocusIn',
        }

        self._layout = None
        self._entryList = []


    # -------------------------------------------------------------------------
    # Implementation of virtual methods
    # -------------------------------------------------------------------------

    def _phase_1_init_(self):
        """
        On phase 1 initialization a logical page registers itself at the logic
        object.
        """

        GFContainer._phase_1_init_(self)

        self._layout = self.findParentOfType('GFLayout')
        self._layout._pageList.append(self)


    # -------------------------------------------------------------------------
    # Rearrange boxes
    # -------------------------------------------------------------------------
    
    def rearrange_boxes(self):
        """
        Calculate the bounding boxes of all GFBox items per page and reparent
        all children which fit into such a GFBox.  As a result all reparented
        children will have their coordinates reset relative to their owning
        box (starting with 0/0 as the top-left position).
        """

        layout = self.findParentOfType('GFLayout')
        boxes = []

        if hasattr(layout, 'Char__width') or hasattr(layout, 'Char__height'):
            for box in self.findChildrenOfType('GFBox', False, True):
                (left, top, width, height) = (box.Char__x, box.Char__y,
                                             box.Char__width, box.Char__height)
                boxes.append((left, top, left+width-1, top+height-1, box))

            boxes.sort()

            for item in self._children[:]:
                if not hasattr(item, 'Char__x'):
                    continue

                left, top = item.Char__x, item.Char__y
                parent = self

                for (bleft, btop, bright, bbottom, box) in boxes:
                    if left > bleft and left < bright and \
                            top > btop and top < bbottom:
                        item.Char__x = left - bleft - 1
                        item.Char__y = top - btop - 1

                        parent._children.remove(item)
                        box.addChild(item)
                        item.setParent(box)
                        parent = box


    # -------------------------------------------------------------------------
    # Focus in and out
    # -------------------------------------------------------------------------

    def focus_in(self):
        """
        Notify the entry that it has received the focus.
        """

        self.processTrigger('PRE-FOCUSIN')
        self.processTrigger('POST-FOCUSIN')

        self._form.update_page_counter()

    # -------------------------------------------------------------------------

    def validate(self):
        """
        Validate the entry to decide whether the focus can be moved away from
        it.

        This function can raise an exception, in which case the focus change
        will be prevented.

        Calling this function will implicitly update the value in the
        associated GFField object.
        """

        self.processTrigger('PRE-FOCUSOUT')


    # -------------------------------------------------------------------------

    def focus_out(self):
        """
        Notify the entry that it is going to lose the focus.

        The focus change is already decided at this moment, there is no way to
        stop the focus from changing now.
        """

        self.processTrigger('POST-FOCUSOUT')
