###############################################################################
# $Id: gvrasterpropdlg.py,v 1.48.2.2 2004/04/02 17:29:50 gmwalter Exp $
#
# Project:  OpenEV
# Purpose:  GvRasterLayer Properties Dialog
# Author:   Frank Warmerdam, warmerda@home.com
#
###############################################################################
# Copyright (c) 2000, Atlantis Scientific Inc. (www.atlsci.com)
# 
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
# 
# This library 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
# Library General Public License for more details.
# 
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
###############################################################################
# 
#  $Log: gvrasterpropdlg.py,v $
#  Revision 1.48.2.2  2004/04/02 17:29:50  gmwalter
#  Fix initialization bug from last changes.
#
#  Revision 1.48.2.1  2004/04/02 17:05:31  gmwalter
#  Updated nodata support for complex and
#  rgb data.
#
#  Revision 1.48  2004/02/20 12:34:19  andrey_kiselev
#  Generate different band names to avoid problems with equally named keys.
#
#  Revision 1.47  2004/01/22 21:28:42  andrey_kiselev
#  New control to display and change NODATA value for viewed RasterSource.
#
#  Revision 1.46  2003/11/05 20:27:23  gmwalter
#  Fix to allow dialog to recognize GCPProjection string if Projection
#  string isn't present.
#
#  Revision 1.45  2003/06/17 14:58:39  gmwalter
#  gvplot: changed so that graphs don't immediately disappear
#  in the gnuplot terminal case.
#  gvrasterpropdlg: fix so that user can go back to opaque white modulation
#  colour.
#
#  Revision 1.44  2003/04/30 15:05:24  gmwalter
#  Fixed a typo that was preventing a tuple from being formed and causing
#  bands to wrap around.
#
#  Revision 1.43  2003/02/20 19:27:22  gmwalter
#  Updated link tool to include Diana's ghost cursor code, and added functions
#  to allow the cursor and link mechanism to use different gcps
#  than the display for georeferencing.  Updated raster properties
#  dialog for multi-band case.  Added some signals to layerdlg.py and
#  oeattedit.py to make it easier for tools to interact with them.
#  A few random bug fixes.
#
#  Revision 1.42  2002/12/17 16:11:47  gmwalter
#  Clamp lower bound of Scale_Max to 0.0 in RLM_COMPLEX case in gui_refresh
#  to avoid confusing phase flips at the 0 crossing when phase display is used.
#
#  Revision 1.41  2002/03/04 21:52:26  warmerda
#  add support for band names
#
#  Revision 1.40  2002/03/04 16:26:42  warmerda
#  added greyscale lock option for RGB layers
#
#  Revision 1.39  2001/10/17 16:24:55  warmerda
#  move complex luts to gview.py
#
#  Revision 1.38  2001/10/12 19:25:15  warmerda
#  improved logic for setting the initial scaling min/max of the scaling controls
#
#  Revision 1.37  2001/08/22 02:16:28  warmerda
#  ensure that gvraster reference not kept from GvRasterSource
#
#  Revision 1.36  2001/07/24 21:21:45  warmerda
#  added EV style phase colormap
#
#  Revision 1.35  2001/07/16 15:20:40  warmerda
#  switched around so magnitude is default for complex layers
#
#  Revision 1.34  2001/04/03 02:29:30  warmerda
#  improved some pane geometry
#
#  Revision 1.33  2001/03/19 21:57:14  warmerda
#  expand tabs
#
#  Revision 1.32  2000/08/25 20:20:03  warmerda
#  added limited nodata support, upped max band count to 30
#
#  Revision 1.31  2000/08/11 20:17:15  warmerda
#  added metadata to image info, made scrollable
#
#  Revision 1.30  2000/08/11 19:19:31  warmerda
#  don't show scaling min for complex layers
#

from gtk import *
from string import *
import gvutils
import pgucolorsel
import sys
import gdal
import osr
import gvhtml

from gvconst import *
import gview

prop_dialog_list = []

def LaunchRasterPropDialog(layer):
    # Check list to see if dialog exists - make it visible
    for test_dialog in prop_dialog_list:
        if test_dialog.layer._o == layer._o:
            test_dialog.update_gui()
            test_dialog.show()
            test_dialog.get_window()._raise()
            return test_dialog

    # Create new dialog if one doesn't exist already
    new_dialog = GvRasterPropDialog(layer)
    prop_dialog_list.append( new_dialog )
    return new_dialog

class GvRasterSource(GtkFrame):
    def __init__(self,name,layer,src_index,master_dialog):
        GtkFrame.__init__(self,name)
        self.master_dialog = master_dialog
        self.updating = FALSE
        self.src_index = src_index

        # Eventually the following will have to be more sophisticated.
        if layer is not None:
            self.layer = layer
            self.gvraster = layer.get_parent()
            self.display_change_id = layer.connect('display-change',
                                                   self.gui_refresh)

        vbox = GtkVBox(spacing=5)
        vbox.set_border_width(5)
        self.add(vbox)
        self.updating = TRUE
        
        # ------ Band Selection -------
        hbox = GtkHBox(spacing=5)
        vbox.pack_start(hbox,expand=FALSE)
        hbox.pack_start(GtkLabel('Band:'))
        self.band_combo = GtkCombo()
        hbox.pack_start(self.band_combo)
        self.band_combo.entry.connect('changed', self.set_band_cb)
        self.band_combo.entry.connect('key_press_event', self.combo_entry_key_press_cb )
        prototype_data = self.layer.get_parent()
        band_list = ['constant']
        ds = prototype_data.get_dataset()
        band_count = ds.RasterCount

        # Fill in the dictionary
        #
        self.__bandDic = {}
        self.__allBands = []
        self.__bandNums = []
        for band in range(band_count) :
            bandKey = self.band_desc(band+1)
            self.__allBands.append( bandKey )
            self.__bandNums.append( str(band+1) )
            self.__bandDic[bandKey] = str(band+1)

        for band in range(min(30,band_count)):
            band_list.append( self.band_desc(band+1) )

        if band_count > 30:
            band_list.append( '...'+self.__allBands[-1] )

        self.band_combo.set_popdown_strings( band_list )

        # ------ Establish scaling range ------

        smin = layer.min_get(src_index)
        smax = layer.max_get(src_index)
        delta = smax - smin
        smax = smax + delta * 0.25
        smin = smin - delta * 0.25
        
        if self.layer.get_mode() == gview.RLM_COMPLEX:
            smin = 0.0
        elif self.layer.get_parent().get_band().DataType == gdal.GDT_Byte:
            smin = 0
            smax = 255
        elif self.layer.get_parent().get_band().DataType == gdal.GDT_UInt16:
            smin = 0
        elif self.layer.get_parent().get_band().DataType == gdal.GDT_UInt32:
            smin = 0
        
        # ------ Scale Min -------
        hbox = GtkHBox(spacing=5)
        self.min_hbox = hbox
        vbox.pack_start(hbox)
        hbox.pack_start(GtkLabel('Scale Min:'),expand=FALSE)
        self.min_adjustment = GtkAdjustment(layer.min_get(src_index),
                                            smin, smax, 1,1,1)
        self.min_adjustment.connect('value-changed',self.adjustment_cb)
        self.min_slider = GtkHScale(self.min_adjustment)
        hbox.pack_start(self.min_slider)
        self.min_entry = GtkEntry(maxlen=8)
        self.min_entry.connect('activate',self.entry_cb)
        self.min_entry.connect('leave-notify-event',self.entry_cb)
        hbox.pack_start(self.min_entry,expand=FALSE)

        # ------ Scale Max -------
        hbox = GtkHBox(spacing=5)
        self.max_hbox = hbox
        vbox.pack_start(hbox)
        hbox.pack_start(GtkLabel('Scale Max:'),expand=FALSE)
        self.max_adjustment = GtkAdjustment(layer.max_get(src_index),
                                            smin, smax, 1,1,1)
        self.max_adjustment.connect('value-changed',self.adjustment_cb)
        self.max_slider = GtkHScale(self.max_adjustment)
        hbox.pack_start(self.max_slider)
        self.max_entry = GtkEntry(maxlen=8)
        self.max_entry.connect('activate',self.entry_cb)
        self.max_entry.connect('leave-notify-event',self.entry_cb)
        hbox.pack_start(self.max_entry,expand=FALSE)

        # ------ NODATA -------
        hbox = GtkHBox(spacing=5)
        self.nodata_hbox = hbox
        vbox.pack_start(hbox)
        hbox.pack_start(GtkLabel('NODATA value:'), expand=FALSE)
        self.nodata_entry = GtkEntry(maxlen=19)
        self.nodata_entry.connect('activate', self.entry_cb)
        self.nodata_entry.connect('leave-notify-event', self.entry_cb)
        hbox.pack_start(self.nodata_entry, expand=FALSE)
        if (src_index < 3) and (ds.RasterCount > src_index):
            nodata=ds.GetRasterBand(src_index+1).GetNoDataValue()
            if nodata is not None:
                if (type(nodata) != type(complex(1,0))):
                    nodata=complex(nodata,0)
                self.layer.nodata_set(src_index,nodata.real,nodata.imag)
            
        # ------- Constant Value -----
        self.const_entry = GtkEntry(maxlen=8)
        self.const_entry.connect('activate',self.const_cb)
        self.const_entry.connect('leave-notify-event',self.const_cb)
        vbox.pack_start(self.const_entry)

        self.updating = FALSE
            
        self.gui_refresh()
        
        self.connect( 'destroy', self.cleanup)

    def combo_entry_key_press_cb( self, entryBox, event, *args ) :
        import GDK

        if self.updating:
            return

        if( event.keyval == GDK.Right ) :
            try :
                currentIndex = self.__allBands.index( entryBox.get_text() )
                nextIndex = min( len(self.__allBands)-1, currentIndex+1 )
                entryBox.set_text( self.__allBands[nextIndex] )
            except ValueError : 
                return

        elif( event.keyval == GDK.Left ) : 
            try :
                currentIndex = self.__allBands.index( entryBox.get_text() )
                prevIndex = max( 0, currentIndex - 1 )
                entryBox.set_text( self.__allBands[prevIndex] )
            except ValueError : 
                return

        elif( event.keyval == GDK.Return ) : 
            entryText = entryBox.get_text()
            if( entryText in self.__bandDic.keys() ) : 
                pass
            else : 
                try :
                    bandIndex = self.__bandNums.index(entryText)
                    entryBox.set_text( self.__allBands[bandIndex] )
                except ValueError : 
                    entryBox.set_text("")
                except KeyError :
                    entryBox.set_text("")
        
    def __del__(self):
        print 'Destroying GvRasterSource'

    def cleanup(self, *args):
        self.layer = None
        self.gvraster = None

    def band_desc(self,iband):
        band = self.layer.get_parent().get_dataset().GetRasterBand(iband)
        if len(band.GetDescription()) > 0:
	    # XXX: band descriptions must be different, because we will use
	    # them as keys in dictionary. That's why we print band number
	    # here.
            return '%d: %s' % (iband,band.GetDescription())
        else:
            return '%d' % iband
        
    def gui_refresh(self, *args):

        if self.layer is None:
            return
        
        if self.flags( DESTROYED ) > 0:
            self.layer.disconnect( self.display_change_id )
            return

        if self.updating:
            return

        self.updating = TRUE
        if self.layer.get_mode() == gview.RLM_COMPLEX:
            new_min = max(0.0,self.layer.min_get(self.src_index))
        else:
            new_min = self.layer.min_get(self.src_index)

        if self.layer.min_get(self.src_index) < self.min_adjustment.lower:               
            self.min_adjustment.set_all( new_min,
                                         new_min,
                                         self.min_adjustment.upper,
                                         self.min_adjustment.step_increment,
                                         self.min_adjustment.page_increment,
                                         self.min_adjustment.page_size)
            self.min_adjustment.changed()                
            self.max_adjustment.set_all( new_min,
                                         new_min,
                                         self.max_adjustment.upper,
                                         self.max_adjustment.step_increment,
                                         self.max_adjustment.page_increment,
                                         self.max_adjustment.page_size)
            self.max_adjustment.changed()
            
        if self.layer.max_get(self.src_index) > self.max_adjustment.upper:
            self.min_adjustment.set_all( new_min,
                                         self.min_adjustment.lower,
                                         self.layer.max_get(self.src_index),
                                         self.min_adjustment.step_increment,
                                         self.min_adjustment.page_increment,
                                         self.min_adjustment.page_size)
            self.min_adjustment.changed()
            self.max_adjustment.set_all( new_min,
                                         self.max_adjustment.lower,
                                         self.layer.max_get(self.src_index),
                                         self.max_adjustment.step_increment,
                                         self.max_adjustment.page_increment,
                                         self.max_adjustment.page_size)
            self.max_adjustment.changed()

        self.min_adjustment.set_value(new_min)
        self.min_entry.set_text(str(new_min))
            
        self.max_adjustment.set_value(self.layer.max_get(self.src_index))
        self.max_entry.set_text(str(self.layer.max_get(self.src_index)))
        nodata=self.layer.nodata_get(self.src_index)
        if type(nodata) == type((1,)):
  	    self.nodata_entry.set_text(str(nodata[0])+'+'+str(nodata[1])+
                                       'j')
        else:
  	    self.nodata_entry.set_text(str(nodata))
            
        self.const_entry.set_text( \
                str(self.layer.get_const_value(self.src_index)))
        
        if self.layer.get_data(self.src_index) is None:
            self.const_entry.show()
            self.min_hbox.hide()
            self.max_hbox.hide()
            self.nodata_hbox.hide()
            self.band_combo.entry.set_text('constant')
        else:
            self.const_entry.hide()
            self.max_hbox.show()
            if self.layer.get_mode() != gview.RLM_COMPLEX:
                self.min_hbox.show()
            else:
                self.min_hbox.hide()
            self.nodata_hbox.show()

            # Set the band selector.
            band = self.layer.get_data(self.src_index).get_band()
            dataset = self.layer.get_data(self.src_index).get_dataset()
            for iband in range(dataset.RasterCount):
                test_band = dataset.GetRasterBand(iband+1)
                if test_band._o == band._o:
                    self.band_combo.entry.set_text(self.band_desc(iband+1))
                    break

        self.updating = FALSE

    def set_band_cb(self,*args):
        if self.updating:
            return

        if self.band_combo.entry.get_text() == 'constant':
            self.layer.set_source(self.src_index, None,
                                  self.layer.min_get(self.src_index),
                                  self.layer.max_get(self.src_index),
                                  self.layer.get_const_value(self.src_index),
                                  self.layer.source_get_lut(self.src_index),
                                  None)
        else:
            try:            
                tokens = self.__bandDic[self.band_combo.entry.get_text()],
            except KeyError :
                tokens = ""
                
            try:
                band_number = int(tokens[0])
            except:
                return

            dataset = self.layer.get_parent().get_dataset()
            raster = gview.manager.get_dataset_raster( dataset, band_number )
            if raster is not None:
                if( self.layer.get_property('_scale_lock') is not None and 
                    self.layer.get_property('_scale_lock') == 'locked' ) : 

                    if( self.layer.get_property("_scale_limits") ) :
                        rasterMin, rasterMax = \
                            map(atof, split(self.layer.get_property("_scale_limits")))
                else :
                    rasterMin = raster.get_min()
                    rasterMax = raster.get_max()

                self.layer.set_source(self.src_index, raster,
                                    rasterMin, rasterMax,
                                    self.layer.get_const_value(self.src_index),
                                    self.layer.source_get_lut(self.src_index),
                          dataset.GetRasterBand(band_number).GetNoDataValue())
                
        if self.src_index < 3 and self.master_dialog.greyscale_is_set():
            self.master_dialog.enforce_greyscale(self.src_index)

        # enable alpha support if user modifies alpha band.
        if self.src_index == 3:
            self.layer.blend_mode_set( RL_BLEND_FILTER )

        self.gui_refresh()
        
    def adjustment_cb(self,adjustment,*args):
        if self.updating:
            return

        value = adjustment.value
        if value < -1 or value > 1:
            value = int(value*10) / 10.0

        if adjustment == self.min_adjustment:
            self.layer.min_set( self.src_index, value )
        else:
            self.layer.max_set( self.src_index, value )
        
        if self.src_index < 3 and self.master_dialog.greyscale_is_set():
            self.master_dialog.enforce_greyscale(self.src_index)

    
    def entry_cb(self,entry,*args):
        if self.updating:
            return

        try:
            value = complex(entry.get_text())
	except:
	    return

	if entry == self.min_entry:
	    self.layer.min_set( self.src_index, value.real )
	elif entry == self.max_entry:
	    self.layer.max_set( self.src_index, value.real )
	else:
            self.layer.nodata_set( self.src_index, value.real, value.imag )

        if self.src_index < 3 and self.master_dialog.greyscale_is_set():
            self.master_dialog.enforce_greyscale(self.src_index)

    def const_cb(self,entry,*args):
        if self.updating:
            return

        try:
            self.layer.set_source(self.src_index,
                                  self.layer.get_data(self.src_index),
                                  self.layer.min_get(self.src_index),
                                  self.layer.max_get(self.src_index),
                                  int(entry.get_text()),
                                  self.layer.source_get_lut(self.src_index),
                                  self.layer.nodata_get(self.src_index))
        except:
            self.const_entry.set_text( \
                str(self.layer.get_const_value(self.src_index)))

        # enable alpha support if user modifies alpha band.
        if self.src_index == 3:
            self.layer.blend_mode_set( RL_BLEND_FILTER )
    
        if self.src_index < 3 and self.master_dialog.greyscale_is_set():
            self.master_dialog.enforce_greyscale(self.src_index)

class GvRasterPropDialog(GtkWindow):

    def __init__(self, layer):
        GtkWindow.__init__(self)
        self.set_border_width(3)
        if layer is not None:
            self.set_title(layer.get_name()+' Properties')
        else:
            self.set_title('Raster Properties')

        gvhtml.set_help_topic( self, "gvrasterpropdlg.html" )
        self.layer = layer
        self.updating = FALSE

        if self.layer is not None:
            self.display_change_id = self.layer.connect('display-change',
                                                        self.refresh_cb)
            self.teardown_id = layer.connect('teardown',self.close)

        
        # create the general layer properties dialog
        self.create_notebook()

        self.create_pane1()
        
        self.updating = TRUE
        self.create_sourcepane()
        self.updating = FALSE
        
        self.create_openglprop()
        self.create_lutprop()
        self.create_imageinfo()

        self.update_gui()
        self.show_all()
        self.update_gui()
        
        for source in self.sources:
            source.gui_refresh()

    def __del__(self):
        print 'disconnect:', self.display_change_id
        self.layer.disconnect(self.display_change_id)

    def create_notebook(self):
        self.notebook = GtkNotebook()
        self.add( self.notebook )
        self.connect('delete-event', self.close)

    def create_lutprop(self):
        
        self.lut_pane = GtkVBox(spacing=10)
        self.lut_pane.set_border_width(10)
        self.notebook.append_page( self.lut_pane, GtkLabel('LUT'))

        self.lut_preview = GtkPreview()
        self.lut_preview.size(256,32)
        self.lut_pane.pack_start(self.lut_preview)

        self.complex_lut_om = \
            gvutils.GvOptionMenu(('Magnitude', 'Phase',
                                  'Magnitude & Phase', 'Real','Imaginary'),
                                 self.complex_lut_cb)
        self.lut_pane.pack_start(self.complex_lut_om, expand=FALSE)

    def create_sourcepane(self):
        self.sources = []
        self.source_pane = GtkVBox(spacing=10)
        self.source_pane.set_border_width(10)
        self.notebook.append_page( self.source_pane, GtkLabel('Raster Source'))

        if self.layer.get_mode() == gview.RLM_RGBA:

            source = GvRasterSource('Red',self.layer,0,self)
            self.source_pane.pack_start(source, expand=FALSE)
            self.sources.append(source)
            
            source = GvRasterSource('Green',self.layer,1,self)
            self.source_pane.pack_start(source, expand=FALSE)
            self.sources.append(source)
            
            source = GvRasterSource('Blue',self.layer,2,self)
            self.source_pane.pack_start(source, expand=FALSE)
            self.sources.append(source)
            
            source = GvRasterSource('Alpha',self.layer,3,self)
            self.source_pane.pack_start(source, expand=FALSE)
            self.sources.append(source)

            self.grey_toggle = GtkCheckButton(label='Greyscale Lock')
            self.grey_toggle.connect('toggled', self.greyscale_cb)
            self.source_pane.pack_start(self.grey_toggle, expand=FALSE)
            self.grey_toggle.set_active( self.greyscale_is_set() )

            scaleHBox = GtkHBox(spacing=10)
            self.scale_toggle = GtkCheckButton(label="Scale Lock")
            self.scale_min_entry = GtkEntry()
            self.scale_max_entry = GtkEntry()
            self.scale_min_entry.connect( "activate", self.activateLockEntry_cb )
            self.scale_max_entry.connect( "activate", self.activateLockEntry_cb )
            w, h = self.scale_min_entry.size_request()
            self.scale_min_entry.set_usize(50, h)
            self.scale_max_entry.set_usize(50, h)


            scaleHBox.pack_start( self.scale_toggle    ) 
            scaleHBox.pack_start( self.scale_min_entry )
            scaleHBox.pack_start( self.scale_max_entry )
            
            self.scale_toggle.connect( "toggled", self.scalelock_cb)
            self.source_pane.pack_start( scaleHBox, expand=FALSE )
            self.scale_toggle.set_active( self.scalelock_is_set() )
            
        else:
            source = GvRasterSource('Raster',self.layer,0,self)
            self.source_pane.pack_start(source, expand=FALSE)
            self.sources.append(source)
        
    def create_pane1(self):
        # Setup General Properties Tab
        self.pane1 = GtkVBox(spacing=10)
        self.pane1.set_border_width(10)
        self.notebook.append_page( self.pane1, GtkLabel('General'))

        # Setup layer name entry box.
        box = GtkHBox(spacing=5)
        self.pane1.pack_start(box, expand=FALSE)
        label = GtkLabel('Layer:' )
        box.pack_start(label,expand=FALSE)
        self.layer_name = GtkEntry()
        self.layer_name.connect('changed', self.name_cb)
        box.pack_start(self.layer_name)

        # Setup Visibility radio buttons.
        vis_box = GtkHBox(spacing=5)
        self.pane1.pack_start(vis_box, expand=FALSE)
        vis_box.pack_start(GtkLabel('Visibility:'),expand=FALSE)
        self.vis_yes = GtkRadioButton(label='yes')
        self.vis_yes.connect('toggled', self.visibility_cb)
        vis_box.pack_start(self.vis_yes,expand=FALSE)
        self.vis_no = GtkRadioButton(label='no',group=self.vis_yes)
        self.vis_no.connect('toggled', self.visibility_cb)
        vis_box.pack_start(self.vis_no,expand=FALSE)

        # Setup Editability radio buttons.
        edit_box = GtkHBox(spacing=5)
        self.pane1.pack_start(edit_box, expand=FALSE)
        edit_box.pack_start(GtkLabel('Editable:'),expand=FALSE)
        self.edit_yes = GtkRadioButton(label='yes')
        self.edit_yes.connect('toggled', self.edit_cb)
        edit_box.pack_start(self.edit_yes,expand=FALSE)
        self.edit_no = GtkRadioButton(label='no',group=self.edit_yes)
        self.edit_no.connect('toggled', self.edit_cb)
        edit_box.pack_start(self.edit_no,expand=FALSE)

    def create_openglprop(self):
        self.oglpane = GtkVBox(spacing=10)
        self.oglpane.set_border_width(10)
        self.notebook.append_page( self.oglpane, GtkLabel('Draw Style'))

        # Create Modulation Color
        box = GtkHBox(spacing=3)
        self.oglpane.pack_start(box, expand=FALSE)
        box.pack_start(GtkLabel('Modulation Color:'),expand=FALSE)
        self.mod_color = pgucolorsel.ColorControl('Modulation Color',
                                                  self.color_cb,None)
        box.pack_start(self.mod_color)

        # Create Interpolation Control
        box = GtkHBox(spacing=3)
        self.oglpane.pack_start(box, expand=FALSE)
        box.pack_start(GtkLabel('Subpixel Interpolation:'),expand=FALSE)
        self.interp_om = gvutils.GvOptionMenu(('Linear','Off (Nearest)'),
                                              self.set_interp_cb)
        box.pack_start(self.interp_om,expand=FALSE)

    def create_imageinfo(self):
        self.iipane = GtkVBox(spacing=10)
        self.iipane.set_border_width(10)
        self.notebook.append_page( self.iipane, GtkLabel('Image Info') )

        self.ii_text = GtkText()
        self.ii_text.set_line_wrap(FALSE)
        self.ii_text.set_word_wrap(FALSE)
        self.ii_text.set_editable(FALSE)
        self.ii_text.show()

        self.ii_scrollwin = GtkScrolledWindow()
        self.ii_scrollwin.add( self.ii_text)
        self.iipane.pack_start(self.ii_scrollwin,expand=TRUE)

        # Now create and assign the text contents.
        gdal_ds = self.layer.get_parent().get_dataset()

        text = ''

        text = text + 'Filename: ' + gdal_ds.GetDescription() + '\n'

        text = text + 'Size: ' + str(gdal_ds.RasterXSize) + 'P x '
        text = text +            str(gdal_ds.RasterYSize) + 'L x '
        text = text +            str(gdal_ds.RasterCount) + 'Bands\n'

        driver = gdal_ds.GetDriver()
        text = text + 'Driver: ' + driver.LongName + '\n'

        transform = gdal_ds.GetGeoTransform()
        if transform[2] == 0.0 and transform[4] == 0.0:
            text = text + 'Origin: ' + str(transform[0])               \
                               + ' ' + str(transform[3]) + '\n'
            text = text + 'Pixel Size: ' + str(transform[1])           \
                                 + ' x ' + str(transform[5]) + '\n'
                                               
        projection = gdal_ds.GetProjection()
        if ((projection is None) or (len(projection) == 0)):
            projection = gdal_ds.GetGCPProjection()

        if projection is None:
            projection=""
            
        if len(projection) > 0:
            sr = osr.SpatialReference()
            if sr.ImportFromWkt( projection ) == 0:
                projection = sr.ExportToPrettyWkt( simplify = 1 )

        text = text + 'Projection:\n'
        text = text + projection + '\n'

        metadata = gdal_ds.GetMetadata()
        if len(metadata) > 0:
            text = text + 'Metadata:\n'
            for item in metadata.items():
                text = text + '    '+item[0]+': '+item[1]+'\n'

        for band_index in range(gdal_ds.RasterCount):
            band = gdal_ds.GetRasterBand(band_index+1)

            text = text + 'Band %2d: Type=' % (band_index+1)
            text = text + gdal.GetDataTypeName(band.DataType)
            if len(band.GetDescription()) > 0:
                text = text + ' - ' + band.GetDescription()
            text = text + '\n'

        self.ii_text.insert_defaults(text)

    # Initialize GUI state from underlying object state.
    def update_gui(self):
        if self.layer is None or self.updating == TRUE:
            return

        self.updating = TRUE
        
        # Layer name.
        self.layer_name.set_text( self.layer.get_name() )
        
        # Visibility radio buttons
        self.vis_yes.set_active( self.layer.is_visible() )
        self.vis_no.set_active( not self.layer.is_visible() )

        # Editability radio buttons
        self.edit_yes.set_active( not self.layer.is_read_only() )
        self.edit_no.set_active( self.layer.is_read_only() )

        # modulation color
        tflag, tcolor = self.layer.texture_mode_get()
        if tflag == 0:
            tcolor = (1,1,1,1)
        self.mod_color.set_color(tcolor)

        # Interpolation Mode
        zmin, zmax = self.layer.zoom_get()
        if zmax == RL_FILTER_BILINEAR:
            self.interp_om.set_history(0)
        else:
            self.interp_om.set_history(1)

        self.updating = FALSE

        # LUT
        lut_tuple = self.layer.lut_get()
        if lut_tuple is None:
            self.lut_pane.hide()
        elif lut_tuple[2] == 1:
            lut_rgba = lut_tuple[0]
            lut_rgb = gview.rgba_to_rgb(lut_rgba)
            
            self.lut_pane.show()
            self.lut_preview.size(256,32)

            for i in range(32):
                self.lut_preview.draw_row( lut_rgb, 0, i, 256)

            self.complex_lut_om.hide()
            self.lut_preview.queue_draw()
        else:
            lut_rgba = lut_tuple[0]
            lut_rgb = gview.rgba_to_rgb(lut_rgba)
            
            self.lut_pane.show()
            self.lut_preview.size(256,256)
            for row in range(256):
                row_data = lut_rgb[row*768:(row+1)*768]
                self.lut_preview.draw_row( row_data, 0, row, 256)

            self.complex_lut_om.show()
            self.lut_preview.queue_draw()

    def name_cb(self, *args):
        if self.layer_name.get_text() != self.layer.get_name():
            self.layer.set_name( self.layer_name.get_text() )

    # Visibility changing
    def visibility_cb( self, widget ):
        self.layer.set_visible( self.vis_yes.active )

    # Readonly changing
    def edit_cb( self, widget ):
        self.layer.set_read_only( self.edit_no.active )

    def scalelock_is_set( self ) : 
        if( self.layer.get_property('_scale_lock') is not None and
            self.layer.get_property('_scale_lock') == 'locked' ) :
                return 1
        else :
            return 0

    def activateLockEntry_cb( self, *args ) : 
        if( self.scale_toggle.get_active() ) :
            self.scalelock_cb()

    def scalelock_cb( self, *args ) : 
        if( self.scalelock_is_set() ) : 
            self.layer.set_property('_scale_lock', 'unlocked')
        else :
            self.layer.set_property('_scale_lock', 'locked'  )

        if( self.scalelock_is_set() ):
            try :
                min_scale = atof( self.scale_min_entry.get_text() )
                max_scale = atof( self.scale_max_entry.get_text() )
            except ValueError : 
                min_scale, max_scale = self.layer.min_get(0), self.layer.max_get(0)
                self.scale_min_entry.set_text( str(min_scale) )
                self.scale_max_entry.set_text( str(max_scale) )

            self.layer.set_property \
                ('_scale_limits', str(min_scale) + ' ' + str(max_scale) )

            for iSource in [0,1,2] :
                self.layer.min_set(iSource, min_scale)
                self.layer.max_set(iSource, max_scale)
            
    def greyscale_is_set(self):
        if self.layer.get_property('_greyscale_lock') is not None \
           and self.layer.get_property('_greyscale_lock') == 'locked':
            return 1
        else:
            return 0
    
    def greyscale_cb(self, *args):
        if self.greyscale_is_set():
            self.layer.set_property('_greyscale_lock','unlocked')
        else:
            self.layer.set_property('_greyscale_lock','locked')

        self.grey_toggle.set_active( self.greyscale_is_set() )

        if self.greyscale_is_set():
            self.enforce_greyscale(0)

    def enforce_greyscale(self, isrc):
        if isrc != 0:
            self.layer.set_source(0, self.layer.get_data(isrc),
                                  self.layer.min_get(isrc),
                                  self.layer.max_get(isrc),
                                  self.layer.get_const_value(isrc),
                                  self.layer.source_get_lut(isrc),
                                  self.layer.nodata_get(isrc))

        if isrc != 1:
            self.layer.set_source(1, self.layer.get_data(isrc),
                                  self.layer.min_get(isrc),
                                  self.layer.max_get(isrc),
                                  self.layer.get_const_value(isrc),
                                  self.layer.source_get_lut(isrc),
                                  self.layer.nodata_get(isrc))

        if isrc != 2:
            self.layer.set_source(2, self.layer.get_data(isrc),
                                  self.layer.min_get(isrc),
                                  self.layer.max_get(isrc),
                                  self.layer.get_const_value(isrc),
                                  self.layer.source_get_lut(isrc),
                                  self.layer.nodata_get(isrc))
    
    def complex_lut_cb(self, *args):
        # Magnitude
        if self.complex_lut_om.get_history() == 0:
            method = 'magnitude'
            
        # Phase
        elif self.complex_lut_om.get_history() == 1:
            method = 'phase'

        # Magnitude and Phase
        elif self.complex_lut_om.get_history() == 2:
            method = 'magphase'

        # Real
        elif self.complex_lut_om.get_history() == 3:
            method = 'real'

        # Imaginary
        elif self.complex_lut_om.get_history() == 4:
            method = 'imaginary'

        self.layer.complex_lut( method )
        
        self.update_gui()

    # Set modulation color
    def color_cb( self, color, type ):
        #if color[0] == 1.0 and color[1] == 1.0 \
        #   and color[2] == 1.0 and color[3] == 1.0:
        #    pass
        #else:
        if color[3] != 1.0:
            self.layer.blend_mode_set( RL_BLEND_FILTER )
        self.layer.texture_mode_set( 1, color )
            

    def set_interp_cb(self,*args):
        if self.interp_om.get_history() == 0:
            self.layer.zoom_set(RL_FILTER_BILINEAR,RL_FILTER_BILINEAR)
        else:
            self.layer.zoom_set(RL_FILTER_NEAREST,RL_FILTER_NEAREST)
            
    # Dialog closed, remove references to python object
    def close( self, *args ):
        prop_dialog_list.remove(self)
        self.layer.disconnect(self.display_change_id)
        self.layer.disconnect(self.teardown_id)

        self.sources = None
        self.layer = None
        self.destroy()
        
    # Force GUI Refresh
    def refresh_cb( self, widget, args ):
        self.update_gui()
        
if __name__ == '__main__':
    dialog = GvRasterPropDialog(None)
    dialog.connect('delete-event', mainquit)

    mainloop()
