#-------------------------------------------------------------------------------
#
#  Define standard Enable 'control' components, like text/image labels,
#  push buttons, radio buttons, check boxes, and so on.
#
#  Written by: David C. Morrill
#
#  Date: 10/10/2003
#
#  (c) Copyright 2003 by Enthought, Inc.
#
#  Classes defined: Label
#                   RadioButton
#                   CheckBox
#
#-------------------------------------------------------------------------------

from __future__ import with_statement

# Major library imports
import os.path

# Enthought library imports
from enable.colors import ColorTrait
from traits.api import Bool, Delegate, HasTraits, Str, Trait, \
                                 TraitPrefixList
from traitsui.api import View, Group

# Local relative imports
from component import Component
from base import LEFT, RIGHT, TOP, BOTTOM, HCENTER, VCENTER, EMBOSSED, ENGRAVED, \
                 transparent_color, xy_in_bounds, add_rectangles
from enable_traits import spacing_trait, padding_trait, margin_trait,\
                          border_size_trait, image_trait
from enable_traits import position_trait, font_trait, engraving_trait
from radio_group import RadioStyle, RadioGroup


#-------------------------------------------------------------------------------
#  Constants:
#-------------------------------------------------------------------------------

empty_text_info = ( 0, 0, 0, 0 )
LEFT_OR_RIGHT = LEFT | RIGHT
TOP_OR_BOTTOM = TOP  | BOTTOM


orientation_trait = Trait( 'text', TraitPrefixList( [ 'text', 'component' ] ) )

class LabelTraits ( HasTraits ):

    text              = Str
    font              = font_trait
    text_position     = position_trait("left")
    color             = ColorTrait("black")
    shadow_color      = ColorTrait("white")
    style             = engraving_trait

    image             = image_trait
    image_position    = position_trait("left")
    image_orientation = orientation_trait

    spacing_height    = spacing_trait
    spacing_width     = spacing_trait
    padding_left      = padding_trait
    padding_right     = padding_trait
    padding_top       = padding_trait
    padding_bottom    = padding_trait
    margin_left       = margin_trait
    margin_right      = margin_trait
    margin_top        = margin_trait
    margin_bottom     = margin_trait
    border_size       = border_size_trait
    border_color      = ColorTrait("black")
    bg_color          = ColorTrait("clear")

    enabled           = Bool(True)
    selected          = Bool(False)

    #---------------------------------------------------------------------------
    #  Trait view definitions:
    #---------------------------------------------------------------------------

    traits_view = View(
        Group( 'enabled', 'selected',
               id = 'component' ),
        Group( 'text',   ' ',
               'font',   ' ',
               'color',  ' ',
               'shadow_color', ' ',
               'style',
               id    = 'text',
               style = 'custom' ),
        Group( 'bg_color{Background Color}', '_',
               'border_color', '_',
               'border_size',
               id    = 'border',
               style = 'custom' ),
        Group( 'text_position',      '_',
               'image_position',     '_',
               'image_orientation',  ' ',
               'image',
               id    = 'position',
               style = 'custom' ),
        Group( 'spacing_height', 'spacing_width', '_',
               'padding_left',   'padding_right',
               'padding_top',    'padding_bottom', '_',
               'margin_left',    'margin_right',
               'margin_top',     'margin_bottom',
               id = 'margin' )
        )

default_label_traits = LabelTraits()

#-------------------------------------------------------------------------------
#  'Label' class:
#-------------------------------------------------------------------------------

LabelTraitDelegate       = Delegate( 'delegate', redraw = True )
LayoutLabelTraitDelegate = LabelTraitDelegate( layout = True )
LabelContentDelegate     = LayoutLabelTraitDelegate( content = True )

class Label ( Component ):

    #---------------------------------------------------------------------------
    #  Trait definitions:
    #---------------------------------------------------------------------------

    delegate          = Trait( default_label_traits )
    text              = LabelContentDelegate
    font              = LabelContentDelegate
    text_position     = LayoutLabelTraitDelegate
    color             = LabelTraitDelegate
    shadow_color      = LabelTraitDelegate
    style             = LabelTraitDelegate

    image             = LayoutLabelTraitDelegate
    image_position    = LayoutLabelTraitDelegate
    image_orientation = LayoutLabelTraitDelegate

    spacing_height    = LayoutLabelTraitDelegate
    spacing_width     = LayoutLabelTraitDelegate
    padding_left      = LayoutLabelTraitDelegate
    padding_right     = LayoutLabelTraitDelegate
    padding_top       = LayoutLabelTraitDelegate
    padding_bottom    = LayoutLabelTraitDelegate
    margin_left       = LayoutLabelTraitDelegate
    margin_right      = LayoutLabelTraitDelegate
    margin_top        = LayoutLabelTraitDelegate
    margin_bottom     = LayoutLabelTraitDelegate
    border_size       = LayoutLabelTraitDelegate
    border_color      = LabelTraitDelegate
    bg_color          = LabelTraitDelegate

    enabled           = LabelTraitDelegate
    selected          = LabelTraitDelegate

    #---------------------------------------------------------------------------
    #  Trait view definitions:
    #---------------------------------------------------------------------------

    traits_view = View(
        Group( '<component>', 'enabled', 'selected',
               id = 'component' ),
        Group( '<links>', 'delegate',
               id = 'links' ),
        Group( 'text',         ' ',
               'font',         ' ',
               'color',        ' ',
               'shadow_color', ' ',
               'style',
               id    = 'text',
               style = 'custom' ),
        Group( 'bg_color{Background Color}', '_',
               'border_color', '_',
               'border_size',
               id    = 'border',
               style = 'custom' ),
        Group( 'text_position',      '_',
               'image_position',     '_',
               'image_orientation',  ' ',
               'image',
               id    = 'position',
               style = 'custom' ),
        Group( 'spacing_height', 'spacing_width', '_',
               'padding_left',   'padding_right',
               'padding_top',    'padding_bottom', '_',
               'margin_left',    'margin_right',
               'margin_top',     'margin_bottom',
               id = 'margin' )
    )

    colorchip_map = {
       'fg_color':     'color',
       'bg_color':     'bg_color',
       'shadow_color': 'shadow_color',
       'alt_color':    'border_color'
    }

    #---------------------------------------------------------------------------
    #  Initialize the object:
    #---------------------------------------------------------------------------

    def __init__ ( self, text = '', **traits ):
        self.text = text
        Component.__init__( self, **traits )

    #---------------------------------------------------------------------------
    #  Handle any trait being modified:
    #---------------------------------------------------------------------------

    def _anytrait_changed ( self, name, old, new ):
        trait = self.trait( name )
        if trait.content:
            self.update_text()
        if trait.redraw:
            if trait.layout:
               self.layout()
            self.redraw()

    #---------------------------------------------------------------------------
    #  Return the components that contain a specified (x,y) point:
    #---------------------------------------------------------------------------

    def _components_at ( self, x, y ):
        if self._in_margins( x, y ):
            return [ self ]
        return []

    #---------------------------------------------------------------------------
    #  Return whether not a specified point is inside the component margins:
    #---------------------------------------------------------------------------

    def _in_margins ( self, x, y ):
        ml = self.margin_left
        mb = self.margin_bottom
        return xy_in_bounds( x, y, add_rectangles(
            self.bounds,
            ( ml, mb, -(self.margin_right + ml), -(self.margin_top + mb) ) ) )

    #---------------------------------------------------------------------------
    #  Update any information related to the text content of the control:
    #---------------------------------------------------------------------------

    def update_text ( self ):
        text = self.text
        if text == '':
            self._text    = []
            self._tdx     = []
            self._max_tdx = self._tdy = 0
        else:
            self._text = _text = text.split( '\n' )
            gc = self.gc_temp()
            gc.set_font( self.font )
            max_tdx   = 0
            self._tdx = _tdx = [ 0 ] * len( _text )
            for i, text in enumerate( _text ):
                tdx, tdy, descent, leading = gc.get_full_text_extent( text )
                tdy += descent + 5