From: eficas <> Date: Tue, 17 May 2005 11:54:51 +0000 (+0000) Subject: *** empty log message *** X-Git-Tag: CC_param_poursuite~136 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=4523e2d8899a00de7ff7b56b56a44fc1afbdd151;p=modules%2Feficas.git *** empty log message *** --- diff --git a/Accas/A_AU_PLUS_UN.py b/Accas/A_AU_PLUS_UN.py new file mode 100644 index 00000000..e7742703 --- /dev/null +++ b/Accas/A_AU_PLUS_UN.py @@ -0,0 +1,29 @@ +#@ MODIF A_AU_PLUS_UN Accas DATE 28/01/2005 AUTEUR VABHHTS J.PELLET +# -*- coding: iso-8859-1 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2005 EDF R&D WWW.CODE-ASTER.ORG +# THIS PROGRAM 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 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# ====================================================================== + +from Noyau import N_REGLE +from Validation import V_AU_PLUS_UN + +class AU_PLUS_UN(V_AU_PLUS_UN.AU_PLUS_UN,N_REGLE.REGLE): + """ + La classe utilise l'initialiseur de REGLE. Il n'est pas + nécessaire d'expliciter son initialiseur car + V_AU_PLUS_UN.AU_PLUS_UN n'en a pas + """ diff --git a/Accas/__init__.py b/Accas/__init__.py index e8414f9c..21636df6 100644 --- a/Accas/__init__.py +++ b/Accas/__init__.py @@ -52,6 +52,7 @@ from A_MCSIMP import MCSIMP # Les règles from A_AU_MOINS_UN import AU_MOINS_UN +from A_AU_PLUS_UN import AU_PLUS_UN from A_UN_PARMI import UN_PARMI from A_PRESENT_PRESENT import PRESENT_PRESENT from A_PRESENT_ABSENT import PRESENT_ABSENT diff --git a/Aster/Cata/Macro/__init__.py b/Aster/Cata/Macro/__init__.py index 4aebb58b..a23fff6f 100644 --- a/Aster/Cata/Macro/__init__.py +++ b/Aster/Cata/Macro/__init__.py @@ -19,3 +19,6 @@ # # # ====================================================================== +print 80 +import traceback +traceback.print_stack() diff --git a/Aster/Cata/Macro/calc_fonction_ops.py b/Aster/Cata/Macro/calc_fonction_ops.py new file mode 100644 index 00000000..8a2907bb --- /dev/null +++ b/Aster/Cata/Macro/calc_fonction_ops.py @@ -0,0 +1,322 @@ +#@ MODIF calc_fonction_ops Macro DATE 12/05/2005 AUTEUR DURAND C.DURAND +# -*- coding: iso-8859-1 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2005 EDF R&D WWW.CODE-ASTER.ORG +# THIS PROGRAM 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 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# ====================================================================== + + +def tocomplex(arg): + if arg[0]=='RI' : return complex(arg[1],arg[2]) + if arg[0]=='MP' : return complex(arg[1]*cos(arg[2]),arg[1]*sin(arg[2])) + +def calc_fonction_ops(self,FFT,DERIVE,INTEGRE,LISS_ENVELOP, + SPEC_OSCI,ABS,COMB,COMB_C,COMPOSE,EXTRACTION, + ENVELOPPE,ASSE,CORR_ACCE,PUISSANCE,INVERSE, + NOM_PARA,NOM_RESU,INTERPOL,PROL_DROITE, + PROL_GAUCHE,NOM_PARA_FONC,INTERPOL_FONC,PROL_DROITE_FONC, + PROL_GAUCHE_FONC,**args): + """ + Ecriture de la macro CALC_FONCTION + """ + ier=0 + import types + import string + import copy + from math import pi + from Utilitai.t_fonction import t_fonction,t_fonction_c,t_nappe + from Accas import _F + from Cata.cata import nappe_sdaster,fonction_sdaster,fonction_c + from Utilitai.Utmess import UTMESS + from Numeric import alltrue,less,array,reshape,cos,sin,exp,sqrt + from Numeric import choose,zeros,Float + import aster_fonctions + + ### On importe les definitions des commandes a utiliser dans la macro + DEFI_FONCTION = self.get_cmd('DEFI_FONCTION') + DEFI_NAPPE = self.get_cmd('DEFI_NAPPE') + + ### Comptage commandes + déclaration concept sortant + self.set_icmd(1) + self.DeclareOut('C_out',self.sd) + + ### type de traitement + ### + if (INTEGRE != None): + __ff=INTEGRE['FONCTION'].convert() + if INTEGRE['METHODE']=='TRAPEZE' : __ex=__ff.trapeze(INTEGRE['COEF']) + if INTEGRE['METHODE']=='SIMPSON' : __ex=__ff.simpson(INTEGRE['COEF']) + ### + if (DERIVE != None): + __ff=DERIVE['FONCTION'].convert() + __ex=__ff.derive() + ### + if (INVERSE != None): + __ff=INVERSE['FONCTION'].convert() + __ex=__ff.inverse() + ### + if (ABS != None): + __ff=ABS['FONCTION'].convert() + __ex=__ff.abs() + ### + if (COMPOSE != None): + __ff=COMPOSE['FONC_RESU'].convert() + __fg=COMPOSE['FONC_PARA'].convert() + __ex=__ff[__fg] + ### + if (ASSE != None): + __f0=ASSE['FONCTION'][0].convert() + __f1=ASSE['FONCTION'][1].convert() + __ex=__f0.cat(__f1,ASSE['SURCHARGE']) + ### + if (COMB != None): + if args['LIST_PARA']!=None : vale_x=args['LIST_PARA'].Valeurs() + else : + vale_x=[] + for mcfact in COMB : + vale_x=vale_x+mcfact['FONCTION'].Absc() + vale_x=dict([(i,0) for i in vale_x]).keys() + vale_x.sort() + list_fonc=[] + if isinstance(self.sd,nappe_sdaster): + for mcfact in COMB : + list_fonc.append(mcfact['FONCTION'].convert()) + list_fonch=[] + for f in list_fonc : + __ex=f + for g in list_fonc : + __ex=__ex.homo_support(g) + list_fonch.append(__ex) + list_fonc=list_fonch + elif isinstance(self.sd,fonction_sdaster): + for mcfact in COMB : + __ex=mcfact['FONCTION'].convert() + list_fonc.append(__ex.evalfonc(vale_x)) + + __ex=list_fonc[0] + __ex=__ex*COMB[0]['COEF'] + i=1 + for item in list_fonc[1:] : + item=item*COMB[i]['COEF'] + __ex=__ex+item + i=i+1 + ### + if (COMB_C != None): + if args['LIST_PARA']!=None : vale_x=args['LIST_PARA'].Valeurs() + else : + vale_x=[] + for mcfact in COMB_C : + vale_x=vale_x+mcfact['FONCTION'].Absc() + vale_x=dict([(i,0) for i in vale_x]).keys() + vale_x.sort() + list_fonc=[] + if isinstance(self.sd,nappe_sdaster): + for mcfact in COMB_C : + list_fonc.append(mcfact['FONCTION'].convert()) + list_fonch=[] + for f in list_fonc : + __ex=f + for g in list_fonc : + __ex=__ex.homo_support(g) + list_fonch.appen(__ex) + list_fonc=list_fonch + elif isinstance(self.sd,fonction_sdaster) or isinstance(self.sd,fonction_c): + for mcfact in COMB_C : + __ex=mcfact['FONCTION'].convert(arg='complex') + list_fonc.append(__ex.evalfonc(vale_x)) + + __ex=list_fonc[0] + if COMB_C[0]['COEF_R']!=None: __ex=__ex*complex(COMB_C[0]['COEF_R']) + if COMB_C[0]['COEF_C']!=None: __ex=__ex*tocomplex(COMB_C[0]['COEF_C']) + i=1 + for item in list_fonc[1:] : + if COMB_C[i]['COEF_R']!=None: coef=complex(COMB_C[i]['COEF_R']) + if COMB_C[i]['COEF_C']!=None: coef=tocomplex(COMB_C[i]['COEF_C']) + item=item*coef + __ex=__ex+item + i=i+1 + ### + if (PUISSANCE != None): + __ff=PUISSANCE['FONCTION'].convert() + __ex=__ff + for i in range(PUISSANCE['EXPOSANT']-1) : __ex=__ex*__ff + ### + if (EXTRACTION != None): + if EXTRACTION['PARTIE']=='REEL' : __ex=EXTRACTION['FONCTION'].convert(arg='real') + if EXTRACTION['PARTIE']=='IMAG' : __ex=EXTRACTION['FONCTION'].convert(arg='imag') + if EXTRACTION['PARTIE']=='MODULE' : __ex=EXTRACTION['FONCTION'].convert(arg='modul') + if EXTRACTION['PARTIE']=='PHASE' : __ex=EXTRACTION['FONCTION'].convert(arg='phase') + ### + if (ENVELOPPE != None): + list_fonc=[] + if isinstance(self.sd,nappe_sdaster): + for f in ENVELOPPE['FONCTION'] : list_fonc.append(f.convert()) + list_fonch=[] + for f in list_fonc : + __ff=f + for g in list_fonc : + __ff=__ff.homo_support(g) + list_fonch.append(__ff) + list_fonc=list_fonch + vale_para=list_fonc[0].vale_para + para =list_fonc[0].para + l_fonc_f =[] + for i in range(len(vale_para)): + __ff=list_fonc[0].l_fonc[i] + if ENVELOPPE['CRITERE']=='SUP' : + for f in list_fonc[1:] : __ff=__ff.sup(f.l_fonc[i]) + if ENVELOPPE['CRITERE']=='INF' : + for f in list_fonc[1:] : __ff=__ff.inf(f.l_fonc[i]) + l_fonc_f.append(__ff) + __ex=t_nappe(vale_para,l_fonc_f,para) + elif isinstance(self.sd,fonction_sdaster): + for f in ENVELOPPE['FONCTION'] : list_fonc.append(f.convert()) + __ex=list_fonc[0] + if ENVELOPPE['CRITERE']=='SUP' : + for f in list_fonc[1:] : __ex=__ex.sup(f) + if ENVELOPPE['CRITERE']=='INF' : + for f in list_fonc[1:] : __ex=__ex.inf(f) + ### + if (CORR_ACCE != None): + __ex=CORR_ACCE['FONCTION'].convert() + para=copy.copy(__ex.para) + # suppression de la tendance de l accelero + __ex=__ex.suppr_tend() + # calcul de la vitesse + __ex=__ex.trapeze(0.) + # calcul de la tendance de la vitesse : y = a1*x +a0 + __ex=__ex.suppr_tend() + if CORR_ACCE['CORR_DEPL']=='OUI': + # suppression de la tendance deplacement + # calcul du deplacement : integration + __ex=__ex.trapeze(0.) + # calcul de la tendance du déplacement : y = a1*x +a0 + __ex=__ex.suppr_tend() + # regeneration de la vitesse : derivation + __ex=__ex.derive() + # regeneration de l accelero : derivation + __ex=__ex.derive() + __ex.para=para + ### + if (FFT != None): + if isinstance(self.sd,fonction_c): + __ff=FFT['FONCTION'].convert() + __ex=__ff.fft(FFT['METHODE']) + if isinstance(self.sd,fonction_sdaster): + __ff=FFT['FONCTION'].convert(arg='complex') + __ex=__ff.fft(FFT['METHODE'],FFT['SYME']) + ### + if (SPEC_OSCI != None): + if SPEC_OSCI['AMOR_REDUIT']==None : + l_amor=[0.02,0.05,0.1] + UTMESS('I','CALC_FONCTION',' : génération par défaut de 3 amortissements :'+str(l_amor)) + else : + if type(SPEC_OSCI['AMOR_REDUIT']) not in (types.ListType,types.TupleType): + l_amor=[SPEC_OSCI['AMOR_REDUIT'],] + else : l_amor= SPEC_OSCI['AMOR_REDUIT'] + if SPEC_OSCI['FREQ']==None and SPEC_OSCI['LIST_FREQ']==None: + l_freq=[] + for i in range(56) : l_freq.append( 0.2+0.050*i) + for i in range( 8) : l_freq.append( 3.0+0.075*i) + for i in range(14) : l_freq.append( 3.6+0.100*i) + for i in range(24) : l_freq.append( 5.0+0.125*i) + for i in range(28) : l_freq.append( 8.0+0.250*i) + for i in range( 6) : l_freq.append(15.0+0.500*i) + for i in range( 4) : l_freq.append(18.0+1.000*i) + for i in range(10) : l_freq.append(22.0+1.500*i) + texte=[] + for i in range(len(l_freq)/5) : + texte.append(' %f %f %f %f %f' %tuple(l_freq[i*5:i*5+5])) + UTMESS('I','CALC_FONCTION',' : génération par défaut de 150 fréquences :\n'+'\n'.join(texte)) + elif SPEC_OSCI['LIST_FREQ']!=None: + l_freq=SPEC_OSCI['LIST_FREQ'].Valeurs() + elif SPEC_OSCI['FREQ']!=None: + if type(SPEC_OSCI['FREQ']) not in (types.ListType,types.TupleType): + l_freq=[SPEC_OSCI['FREQ'],] + else : l_freq= SPEC_OSCI['FREQ'] + if abs(SPEC_OSCI['NORME'])<1.E-10 : + UTMESS('S','CALC_FONCTION',' : SPEC_OSCI, la norme ne peut etre nulle') + if SPEC_OSCI['NATURE_FONC']!='ACCE' : + UTMESS('S','CALC_FONCTION',' : SPEC_OSCI, le type de la fonction doit etre ACCE') + if SPEC_OSCI['METHODE']!='NIGAM' : + UTMESS('S','CALC_FONCTION',' : SPEC_OSCI, seule la méthode NIGAM est codée') + eps=1.e-6 + for amor in l_amor : + if amor>(1-eps) : + UTMESS('S','CALC_FONCTION',' : SPEC_OSCI, la méthode choisie '\ + 'suppose des amortissements sous-critiques, amor<1.') + + __ff=SPEC_OSCI['FONCTION'].convert() + + # appel à SPEC_OSCI + spectr = aster_fonctions.SPEC_OSCI(__ff.vale_x, __ff.vale_y, l_freq, l_amor) + + # construction de la nappe + vale_para = l_amor + para = { 'INTERPOL' : ['LIN','LOG'], + 'NOM_PARA_FONC' : 'FREQ', + 'NOM_PARA' : 'AMOR', + 'PROL_DROITE' : 'EXCLU', + 'PROL_GAUCHE' : 'EXCLU', + 'NOM_RESU' : SPEC_OSCI['NATURE'] } + para_fonc = { 'INTERPOL' : ['LOG','LOG'], + 'NOM_PARA' : 'FREQ', + 'PROL_DROITE' : 'CONSTANT', + 'PROL_GAUCHE' : 'EXCLU', + 'NOM_RESU' : SPEC_OSCI['NATURE'] } + if SPEC_OSCI['NATURE']=='DEPL' : ideb = 0 + elif SPEC_OSCI['NATURE']=='VITE' : ideb = 1 + else : ideb = 2 + l_fonc = [] + for iamor in range(len(l_amor)) : + l_fonc.append(t_fonction(l_freq,spectr[iamor,ideb,:]/SPEC_OSCI['NORME'],para_fonc)) + __ex=t_nappe(vale_para,l_fonc,para) + ### + if (LISS_ENVELOP!= None): return + + ### creation de la fonction produite par appel à DEFI_FONCTION + ### on récupère les paramètres issus du calcul de __ex + ### et on les surcharge par ceux imposés par l'utilisateur + + if isinstance(__ex,t_fonction) or isinstance(__ex,t_fonction_c): + para=__ex.para + if NOM_PARA !=None : para['NOM_PARA'] =NOM_PARA + if NOM_RESU !=None : para['NOM_RESU'] =NOM_RESU + if PROL_DROITE!=None : para['PROL_DROITE']=PROL_DROITE + if PROL_GAUCHE!=None : para['PROL_GAUCHE']=PROL_GAUCHE + if INTERPOL !=None : para['INTERPOL'] =INTERPOL + if isinstance(__ex,t_fonction_c): para['VALE_C'] = __ex.tabul() + elif isinstance(__ex,t_fonction) : para['VALE'] = __ex.tabul() + C_out=DEFI_FONCTION(**para) + elif isinstance(__ex,t_nappe): + def_fonc=[] + for f in __ex.l_fonc : + para=f.para + def_fonc.append(_F(VALE =f.tabul(), + INTERPOL =f.para['INTERPOL'], + PROL_DROITE=f.para['PROL_DROITE'], + PROL_GAUCHE=f.para['PROL_GAUCHE'],) + ) + para=__ex.para + if NOM_PARA !=None : para['NOM_PARA'] =NOM_PARA + if NOM_RESU !=None : para['NOM_RESU'] =NOM_RESU + if PROL_DROITE !=None : para['PROL_DROITE']=PROL_DROITE + if PROL_GAUCHE !=None : para['PROL_GAUCHE']=PROL_GAUCHE + if NOM_PARA_FONC !=None : para['NOM_PARA_FONC'] =INTERPOL + if INTERPOL_FONC !=None : para['INTERPOL'] =INTERPOL + C_out=DEFI_NAPPE(PARA=__ex.vale_para.tolist(),DEFI_FONCTION=def_fonc,**para) + return ier + diff --git a/Aster/Cata/Macro/calc_precont_ops.py b/Aster/Cata/Macro/calc_precont_ops.py index b345ca86..a012dfb5 100644 --- a/Aster/Cata/Macro/calc_precont_ops.py +++ b/Aster/Cata/Macro/calc_precont_ops.py @@ -1,4 +1,4 @@ -#@ MODIF calc_precont_ops Macro DATE 22/11/2004 AUTEUR LEBOUVIE F.LEBOUVIER +#@ MODIF calc_precont_ops Macro DATE 07/03/2005 AUTEUR DURAND C.DURAND # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -319,7 +319,7 @@ def calc_precont_ops(self,reuse,MODELE,CHAM_MATER,CARA_ELEM,EXCIT, # 1.6 Blocage de tous les noeuds des cables actifs # -------------------------------------------------- - __B_CA=AFFE_CHAR_MECA(MODELE=__M_CA, + _B_CA=AFFE_CHAR_MECA(MODELE=__M_CA, DDL_IMPO= _F( GROUP_MA = __GROUP_MA_A, DX = 0., DY = 0., @@ -328,11 +328,11 @@ def calc_precont_ops(self,reuse,MODELE,CHAM_MATER,CARA_ELEM,EXCIT, # 1.7 Chargements concernant les cables # ------------------------------------- - __C_CN=AFFE_CHAR_MECA(MODELE=__M_CA,**motscles) - __C_CA=AFFE_CHAR_MECA(MODELE=MODELE,**motscle2) - __C_CT=AFFE_CHAR_MECA(MODELE=MODELE,**motscle3) + _C_CN=AFFE_CHAR_MECA(MODELE=__M_CA,**motscles) + _C_CA=AFFE_CHAR_MECA(MODELE=MODELE,**motscle2) + _C_CT=AFFE_CHAR_MECA(MODELE=MODELE,**motscle3) if CABLE_BP_INACTIF: - __C_CI=AFFE_CHAR_MECA(MODELE=MODELE,**motscle6) + _C_CI=AFFE_CHAR_MECA(MODELE=MODELE,**motscle6) @@ -343,7 +343,7 @@ def calc_precont_ops(self,reuse,MODELE,CHAM_MATER,CARA_ELEM,EXCIT, #------------------------------------------------------------------- # 2.1 Premiere etape : calcul sur le(s) cable(s) et - # recuperation des __F_CAs aux noeuds + # recuperation des _F_CAs aux noeuds # on travaile entre tmin et tmax #------------------------------------------------------------------- @@ -351,8 +351,8 @@ def calc_precont_ops(self,reuse,MODELE,CHAM_MATER,CARA_ELEM,EXCIT, MODELE = __M_CA, CHAM_MATER = CHAM_MATER, CARA_ELEM = CARA_ELEM, - EXCIT =(_F(CHARGE = __B_CA), - _F(CHARGE = __C_CN),), + EXCIT =(_F(CHARGE = _B_CA), + _F(CHARGE = _C_CN),), COMP_INCR =_F( RELATION = 'ELAS', DEFORMATION = 'PETIT', TOUT = 'OUI'), @@ -382,7 +382,7 @@ def calc_precont_ops(self,reuse,MODELE,CHAM_MATER,CARA_ELEM,EXCIT, CHAM_GD=__REA, COEF_R = -1.), ) - __F_CA=AFFE_CHAR_MECA(MODELE=__M_CA, + _F_CA=AFFE_CHAR_MECA(MODELE=__M_CA, VECT_ASSE = __REAC ) @@ -400,12 +400,12 @@ def calc_precont_ops(self,reuse,MODELE,CHAM_MATER,CARA_ELEM,EXCIT, if dExcit[-1][i]==None : del dExcit[-1][i] if CABLE_BP_INACTIF: - dExcit.append(_F(CHARGE=__C_CI),) + dExcit.append(_F(CHARGE=_C_CI),) # Creation du mots-cle EXCIT pour le STAT_NON_LINE dExcit1=copy.copy(dExcit) - dExcit1.append(_F(CHARGE=__C_CA),) - dExcit1.append(_F(CHARGE = __F_CA, + dExcit1.append(_F(CHARGE=_C_CA),) + dExcit1.append(_F(CHARGE = _F_CA, FONC_MULT=__FCT ),) RES=STAT_NON_LINE( @@ -439,7 +439,7 @@ def calc_precont_ops(self,reuse,MODELE,CHAM_MATER,CARA_ELEM,EXCIT, # Creation du mots-cles EXCIT pour le STAT_NON_LINE dExcit2=copy.copy(dExcit) - dExcit2.append(_F(CHARGE=__C_CT,) ) + dExcit2.append(_F(CHARGE=_C_CT,) ) # Calcul sur un seul pas (de __TINT a __TMAX) RES=STAT_NON_LINE( reuse = RES, diff --git a/Aster/Cata/Macro/impr_fonction_ops.py b/Aster/Cata/Macro/impr_fonction_ops.py index 4f2ace21..1e9d6e49 100644 --- a/Aster/Cata/Macro/impr_fonction_ops.py +++ b/Aster/Cata/Macro/impr_fonction_ops.py @@ -1,4 +1,4 @@ -#@ MODIF impr_fonction_ops Macro DATE 30/11/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF impr_fonction_ops Macro DATE 11/05/2005 AUTEUR MCOURTOI M.COURTOIS # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -31,9 +31,10 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): """ macro='IMPR_FONCTION' import aster - from Accas import _F - from Utilitai import Graph - from Utilitai.Utmess import UTMESS + from Accas import _F + from Utilitai import Graph + from Utilitai.Utmess import UTMESS + from Utilitai.UniteAster import UniteAster ier=0 # La macro compte pour 1 dans la numerotation des commandes self.set_icmd(1) @@ -42,21 +43,21 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): # Le nom de la variable doit etre obligatoirement le nom de la commande CALC_FONC_INTERP = self.get_cmd('CALC_FONC_INTERP') DEFI_LIST_REEL = self.get_cmd('DEFI_LIST_REEL') - DEFI_FICHIER = self.get_cmd('DEFI_FICHIER') DETRUIRE = self.get_cmd('DETRUIRE') #---------------------------------------------- # 0. Traitement des arguments, initialisations # unité logique des fichiers réservés ul_reserve=(8,) + UL = UniteAster() # 0.1. Fichier nomfich=None if args['UNITE'] and args['UNITE']<>6: - nomfich='fort.'+str(args['UNITE']) + nomfich=UL.Nom(args['UNITE']) if INFO==2: print ' Nom du fichier :',nomfich - if nomfich and os.path.exists(nomfich): + if nomfich and os.path.exists(nomfich) and os.stat(nomfich).st_size<>0: if FORMAT=='XMGRACE': niv='A' else: @@ -74,7 +75,8 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): for Ci in COURBE: iocc+=1 dC = Ci.cree_dict_valeurs(Ci.mc_liste) - if dC.has_key('LIST_PARA') and i0==0: i0=iocc + if dC.has_key('LIST_PARA') and dC['LIST_PARA']!=None and i0==0: + i0=iocc for mc in dC.keys(): if dC[mc]==None: del dC[mc] Courbe.append(dC) @@ -142,6 +144,7 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): if typ=='nappe_sdaster': lpar,lval=obj.Valeurs() dico,ldicf=obj.Parametres() + Leg=dCi['LEGENDE'] for i in range(len(lpar)): p=lpar[i] lx=lval[i][0] @@ -169,12 +172,16 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): lx=lv2[0][0] ly=lv2[0][1] # on stocke les données dans le Graph + nomresu=dic['NOM_RESU'].strip()+'_'+str(len(graph.Legendes)) dicC={ 'Val' : [lx,ly], - 'Lab' : [dic['NOM_PARA_FONC'],dic['NOM_RESU']] + 'Lab' : [dic['NOM_PARA_FONC'],nomresu] } + # ajoute la valeur du paramètre + dCi['LEGENDE'] = '%s %s=%g' % (Leg,dic['NOM_PARA'].strip(),p) Graph.AjoutParaCourbe(dicC, args=dCi) graph.AjoutCourbe(**dicC) + DETRUIRE(CONCEPT=_F(NOM=('li__','ftmp__'),),ALARME='NON',INFO=1) else: ftmp__=obj dpar=ftmp__.Parametres() @@ -194,17 +201,19 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): lx=lval[0] lr=lval[1] if typ=='fonction_c' and dCi.has_key('PARTIE'): - if dCi['PARTIE']=='COMPLEXE' : lr=lval[2] + if dCi['PARTIE']=='IMAG' : lr=lval[2] # on stocke les données dans le Graph if typ=='fonction_c' and not dCi.has_key('PARTIE'): + nomresu=dpar['NOM_RESU'].strip()+'_'+str(len(graph.Legendes)) dicC={ 'Val' : lval, - 'Lab' : [dpar['NOM_PARA'],dpar['NOM_RESU']+'_R',dpar['NOM_RESU']+'_I'] + 'Lab' : [dpar['NOM_PARA'],nomresu+'_R',nomresu+'_I'] } else: + nomresu=dpar['NOM_RESU'].strip()+'_'+str(len(graph.Legendes)) dicC={ 'Val' : [lx,lr], - 'Lab' : [dpar['NOM_PARA'],dpar['NOM_RESU']] + 'Lab' : [dpar['NOM_PARA'],nomresu] } Graph.AjoutParaCourbe(dicC, args=dCi) graph.AjoutCourbe(**dicC) @@ -275,14 +284,18 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): # on stocke les données dans le Graph # on imprime la liste des paramètres seulement si LIST_PARA if intloc: + nomresur=dpar['NOM_RESU'].strip()+'_'+str(len(graph.Legendes)) + nomresu2=dpa2['NOM_RESU'].strip()+'_'+str(len(graph.Legendes)+1) dicC={ 'Val' : [lt,lx,ly], - 'Lab' : [dpar['NOM_PARA'],dpar['NOM_RESU'],dpa2['NOM_RESU']] + 'Lab' : [dpar['NOM_PARA'],nomresur,nomresu2] } else: + nomresur=dpar['NOM_RESU'].strip()+'_'+str(len(graph.Legendes)) + nomresu2=dpa2['NOM_RESU'].strip()+'_'+str(len(graph.Legendes)+1) dicC={ 'Val' : [lx,ly], - 'Lab' : [dpar['NOM_RESU'],dpa2['NOM_RESU']] + 'Lab' : [nomresur,nomresu2] } Graph.AjoutParaCourbe(dicC, args=dCi) graph.AjoutCourbe(**dicC) @@ -358,7 +371,7 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): elif FORMAT=='AGRAF': nomdigr=None if args['UNITE_DIGR']<>6: - nomdigr='fort.'+str(args['UNITE_DIGR']) + nomdigr=UL.Nom(args['UNITE_DIGR']) kargs['FICHIER']=[nomfich, nomdigr] kargs['dform']={ 'formR' : '%12.5E' } @@ -373,21 +386,15 @@ def impr_fonction_ops(self, FORMAT, COURBE, INFO, **args): # Traiter le cas des UL réservées if args['UNITE'] and args['UNITE'] in ul_reserve: - DEFI_FICHIER( ACTION='LIBERER', UNITE=args['UNITE'], ) + UL.Etat(args['UNITE'], etat='F') if FORMAT=='AGRAF' and args['UNITE_DIGR']<>args['UNITE'] \ and args['UNITE_DIGR'] in ul_reserve: - DEFI_FICHIER( ACTION='LIBERER', UNITE=args['UNITE_DIGR'], ) + UL.Etat(args['UNITE_DIGR'], etat='F') # 2.4. On trace ! graph.Trace(**kargs) # 99. Traiter le cas des UL réservées - if args['UNITE'] and args['UNITE'] in ul_reserve: - DEFI_FICHIER( ACTION='ASSOCIER', UNITE=args['UNITE'], - TYPE='ASCII', ACCES='APPEND' ) - if FORMAT=='AGRAF' and args['UNITE_DIGR']<>args['UNITE'] \ - and args['UNITE_DIGR'] in ul_reserve: - DEFI_FICHIER( ACTION='ASSOCIER', UNITE=args['UNITE_DIGR'], - TYPE='ASCII', ACCES='APPEND' ) + UL.EtatInit() return ier diff --git a/Aster/Cata/Macro/impr_table_ops.py b/Aster/Cata/Macro/impr_table_ops.py index ca1a492f..74776f0b 100644 --- a/Aster/Cata/Macro/impr_table_ops.py +++ b/Aster/Cata/Macro/impr_table_ops.py @@ -1,4 +1,4 @@ -#@ MODIF impr_table_ops Macro DATE 30/11/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF impr_table_ops Macro DATE 11/05/2005 AUTEUR MCOURTOI M.COURTOIS # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -35,9 +35,10 @@ def impr_table_ops(self, FORMAT, TABLE, INFO, **args): """ macro='IMPR_TABLE' import aster - from Accas import _F - from Cata.cata import table_jeveux - from Utilitai.Utmess import UTMESS + from Accas import _F + from Cata.cata import table_jeveux + from Utilitai.Utmess import UTMESS + from Utilitai.UniteAster import UniteAster ier=0 # La macro compte pour 1 dans la numerotation des commandes self.set_icmd(1) @@ -45,19 +46,19 @@ def impr_table_ops(self, FORMAT, TABLE, INFO, **args): # On importe les definitions des commandes a utiliser dans la macro # Le nom de la variable doit etre obligatoirement le nom de la commande DETRUIRE = self.get_cmd('DETRUIRE') - DEFI_FICHIER = self.get_cmd('DEFI_FICHIER') RECU_FONCTION = self.get_cmd('RECU_FONCTION') #---------------------------------------------- # 0. Traitement des arguments, initialisations # unité logique des fichiers réservés ul_reserve=(8,) + UL = UniteAster() # 0.1. Fichier nomfich=None if args['UNITE'] and args['UNITE']<>6: - nomfich='fort.'+str(args['UNITE']) - if nomfich and os.path.exists(nomfich): + nomfich=UL.Nom(args['UNITE']) + if nomfich and os.path.exists(nomfich) and os.stat(nomfich).st_size<>0: if FORMAT=='XMGRACE': UTMESS('A',macro,'Le fichier '+nomfich+' existe déjà, on écrit ' \ 'à la suite.') @@ -111,7 +112,7 @@ def impr_table_ops(self, FORMAT, TABLE, INFO, **args): # 0.4.2. Traiter le cas des UL réservées if args['UNITE'] and args['UNITE'] in ul_reserve: - DEFI_FICHIER( ACTION='LIBERER', UNITE=args['UNITE'], ) + UL.Etat(args['UNITE'], etat='F') #---------------------------------------------- # Boucle sur les tables @@ -205,9 +206,7 @@ def impr_table_ops(self, FORMAT, TABLE, INFO, **args): DETRUIRE(CONCEPT=_F(NOM=('__fonc',),), ALARME='NON', INFO=1,) # 99. Traiter le cas des UL réservées - if args['UNITE'] and args['UNITE'] in ul_reserve: - DEFI_FICHIER( ACTION='ASSOCIER', UNITE=args['UNITE'], - TYPE='ASCII', ACCES='APPEND' ) + UL.EtatInit() return ier diff --git a/Aster/Cata/Macro/info_fonction_ops.py b/Aster/Cata/Macro/info_fonction_ops.py new file mode 100644 index 00000000..b728f6a4 --- /dev/null +++ b/Aster/Cata/Macro/info_fonction_ops.py @@ -0,0 +1,252 @@ +#@ MODIF info_fonction_ops Macro DATE 12/05/2005 AUTEUR DURAND C.DURAND +# -*- coding: iso-8859-1 -*- +# CONFIGURATION MANAGEMENT OF EDF VERSION +# ====================================================================== +# COPYRIGHT (C) 1991 - 2005 EDF R&D WWW.CODE-ASTER.ORG +# THIS PROGRAM 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 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# ====================================================================== +def info_fonction_ops(self,RMS,NOCI_SEISME,MAX,NORME,ECART_TYPE,**args): + """ + Ecriture de la macro INFO_FONCTION + """ + ier=0 + import string + from Utilitai.t_fonction import t_fonction,t_fonction_c,t_nappe + import math + from Accas import _F + from Utilitai.Utmess import UTMESS + + ### On importe les definitions des commandes a utiliser dans la macro + CREA_TABLE = self.get_cmd('CREA_TABLE') + CALC_FONCTION = self.get_cmd('CALC_FONCTION') + + ### Comptage commandes + déclaration concept sortant + self.set_icmd(1) + self.DeclareOut('C_out',self.sd) + + ### type de traitement + + ### + if (MAX != None): + __ff=MAX['FONCTION'].convert() + __ex=__ff.extreme() + n_mini=len(__ex['min']) + n_maxi=len(__ex['max']) + listeMCF=[_F(LISTE_K=[MAX['FONCTION'].nom]*(n_mini+n_maxi),PARA='FONCTION'), + _F(LISTE_K=['MINI',]*n_mini+['MAXI',]*n_maxi,PARA='TYPE'),] + if isinstance(__ff,t_nappe) : + listeMCF=listeMCF+[\ + _F(LISTE_R=[i[0] for i in __ex['min']]+[i[0] for i in __ex['max']],PARA=__ff.para['NOM_PARA']),\ + _F(LISTE_R=[i[1] for i in __ex['min']]+[i[1] for i in __ex['max']],PARA=__ff.para['NOM_PARA_FONC']),\ + _F(LISTE_R=[i[2] for i in __ex['min']]+[i[2] for i in __ex['max']],PARA=__ff.para['NOM_RESU'])] + else : + listeMCF=listeMCF+[\ + _F(LISTE_R=[i[0] for i in __ex['min']]+[i[0] for i in __ex['max']],PARA=__ff.para['NOM_PARA']),\ + _F(LISTE_R=[i[1] for i in __ex['min']]+[i[1] for i in __ex['max']],PARA=__ff.para['NOM_RESU'])] + C_out=CREA_TABLE(LISTE=listeMCF) + + ### + if (ECART_TYPE != None): + __ff=ECART_TYPE['FONCTION'].convert() + if ECART_TYPE['INST_INIT']!=None : tini=ECART_TYPE['INST_INIT'] + else : tini=__ff.vale_x[0] + if ECART_TYPE['INST_FIN' ]!=None : tfin=ECART_TYPE['INST_FIN' ] + else : tfin=__ff.vale_x[-1] + __ff=__ff.cut(tini,__ff.vale_x[-1],ECART_TYPE['PRECISION'],ECART_TYPE['CRITERE']) + __ff=__ff.cut(__ff.vale_x[0],tfin,ECART_TYPE['PRECISION'],ECART_TYPE['CRITERE']) + if ECART_TYPE['METHODE' ]=='SIMPSON' : __ex=__ff.simpson(0.) + if ECART_TYPE['METHODE' ]=='TRAPEZE' : __ex=__ff.trapeze(0.) + fmoy=__ex.vale_y[-1]/(__ff.vale_x[-1]-__ff.vale_x[0]) + __ff=__ff+(-1*fmoy) + __ff=__ff*__ff + if ECART_TYPE['METHODE' ]=='SIMPSON' : __ez=__ff.simpson(0.) + if ECART_TYPE['METHODE' ]=='TRAPEZE' : __ez=__ff.trapeze(0.) + sigma=math.sqrt(__ez.vale_y[-1]/(__ff.vale_x[-1]-__ff.vale_x[0])) + C_out=CREA_TABLE(LISTE=(_F(LISTE_K=ECART_TYPE['FONCTION'].nom,PARA='FONCTION'), + _F(LISTE_K=ECART_TYPE['METHODE'] ,PARA='METHODE'), + _F(LISTE_R=fmoy ,PARA='MOYENNE'), + _F(LISTE_R=sigma ,PARA='ECART_TYPE'), + _F(LISTE_R=tini ,PARA='INST_INIT'), + _F(LISTE_R=tfin ,PARA='INST_FIN'),) + ) + + ### + if (RMS != None): + RMS =list(RMS) + sigm =[] + tmpi =[] + tmpf =[] + nomf =[] + meth =[] + for i_rms in RMS : + __ff=i_rms['FONCTION'].convert() + if i_rms['INST_INIT']!=None : tini=i_rms['INST_INIT'] + else : tini=__ff.vale_x[0] + if i_rms['INST_FIN' ]!=None : tfin=i_rms['INST_FIN' ] + else : tfin=__ff.vale_x[-1] + __ff=__ff.cut(tini,__ff.vale_x[-1],i_rms['PRECISION'],i_rms['CRITERE']) + __ff=__ff.cut(__ff.vale_x[0],tfin,i_rms['PRECISION'],i_rms['CRITERE']) + __ff=__ff*__ff + if i_rms['METHODE' ]=='SIMPSON' : __ez=__ff.simpson(0.) + if i_rms['METHODE' ]=='TRAPEZE' : + __ez=__ff.trapeze(0.) + sigm.append(math.sqrt(__ez.vale_y[-1]/(__ff.vale_x[-1]-__ff.vale_x[0]))) + tmpi.append(tini) + tmpf.append(tfin) + nomf.append(i_rms['FONCTION'].nom) + meth.append(i_rms['METHODE']) + C_out=CREA_TABLE(LISTE=(_F(LISTE_K=nomf ,PARA='FONCTION'), + _F(LISTE_K=meth ,PARA='METHODE'), + _F(LISTE_R=tmpi ,PARA='INST_INIT'), + _F(LISTE_R=tmpf ,PARA='INST_FIN'), + _F(LISTE_R=sigm ,PARA='RMS'), ) + ) + + ### + if (NORME != None): + __ff=NORME['FONCTION'].convert() + norme=[] + for __fi in __ff.l_fonc : + norme.append(__fi.normel2()) + nom=[NORME['FONCTION'].nom,]*len(norme) + C_out=CREA_TABLE(LISTE=(_F(LISTE_R=norme ,PARA='NORME'), + _F(LISTE_K=nom ,PARA='FONCTION'), ) + ) + + ### + if (NOCI_SEISME != None): + l_table=[] + if NOCI_SEISME['SPEC_OSCI'] !=None : + ### cas intensité spectrale d'une nappe de SRO + ### la seule option licite est INTE_SPEC + UTMESS('I','INFO_FONCTION',''' : intensite spectrale, avant de calculer l'\ +intensite spectrale, il est prudent de verifier la norme de la nappe sur laquelle \ +porte le calcul, ceci peut etre une source d erreurs.''') + amor=NOCI_SEISME['AMOR_REDUIT'] + fini=NOCI_SEISME['FREQ_INIT' ] + ffin=NOCI_SEISME['FREQ_FIN' ] + __sp =NOCI_SEISME['SPEC_OSCI'].convert() + vale_x=__sp.l_fonc[0].vale_x + vale_y=[__sp(amor,f) for f in vale_x] + para =__sp.l_fonc[0].para + __srov=t_fonction(vale_x,vale_y,para) + if NOCI_SEISME['NATURE']=='DEPL' : + __srov.vale_y=(__srov.vale_y/__srov.vale_x)*2.*math.pi + elif NOCI_SEISME['NATURE']=='VITE' : + __srov.vale_y=__srov.vale_y/__srov.vale_x/__srov.vale_x + elif NOCI_SEISME['NATURE']=='ACCE' : + __srov.vale_y=__srov.vale_y/__srov.vale_x/__srov.vale_x + __srov.vale_y=__srov.vale_y/__srov.vale_x/2./math.pi + __srov=__srov.cut(fini,ffin,NOCI_SEISME['PRECISION'],NOCI_SEISME['CRITERE']) + insp=__srov.trapeze(0.).vale_y[-1] + l_table.append(_F(LISTE_R=fini ,PARA='FREQ_INIT' )) + l_table.append(_F(LISTE_R=ffin ,PARA='FREQ_FIN' )) + l_table.append(_F(LISTE_R=amor ,PARA='AMOR_REDUIT')) + l_table.append(_F(LISTE_R=insp ,PARA='INTE_SPECT' )) + if NOCI_SEISME['FONCTION'] !=None : + ### cas fonction + l_table.append(_F(LISTE_K=NOCI_SEISME['FONCTION'].nom,PARA='FONCTION')) + __ac=NOCI_SEISME['FONCTION'].convert() + option= NOCI_SEISME['OPTION'] + if NOCI_SEISME['INST_INIT']!=None : tdeb=NOCI_SEISME['INST_INIT'] + else : tdeb=__ac.vale_x[0] + if NOCI_SEISME['INST_FIN' ]!=None : tfin=NOCI_SEISME['INST_FIN' ] + else : tfin=__ac.vale_x[-1] + # calcul de la vitesse : + __vi=__ac.trapeze(NOCI_SEISME['COEF']) + # calcul du déplacement : + __de=__vi.trapeze(NOCI_SEISME['COEF']) + # calcul de |acceleration| : + __aa=__ac.abs() + # calcul de integrale(|acceleration|) : + ### on "coupe" la fonction entre tdeb et tfin + __ac=__ac.cut(tdeb,tfin,NOCI_SEISME['PRECISION'],NOCI_SEISME['CRITERE']) + __vi=__vi.cut(tdeb,tfin,NOCI_SEISME['PRECISION'],NOCI_SEISME['CRITERE']) + __de=__de.cut(tdeb,tfin,NOCI_SEISME['PRECISION'],NOCI_SEISME['CRITERE']) + __aa=__aa.cut(tdeb,tfin,NOCI_SEISME['PRECISION'],NOCI_SEISME['CRITERE']) + if NOCI_SEISME['FREQ' ]!=None : l_freq=NOCI_SEISME['FREQ'] + elif NOCI_SEISME['LIST_FREQ']!=None : l_freq=NOCI_SEISME['LIST_FREQ'].Valeurs() + else : + # fréquences par défaut + l_freq=[] + for i in range(56) : l_freq.append( 0.2+0.050*i) + for i in range( 8) : l_freq.append( 3.0+0.075*i) + for i in range(14) : l_freq.append( 3.6+0.100*i) + for i in range(24) : l_freq.append( 5.0+0.125*i) + for i in range(28) : l_freq.append( 8.0+0.250*i) + for i in range( 6) : l_freq.append(15.0+0.500*i) + for i in range( 4) : l_freq.append(18.0+1.000*i) + for i in range(10) : l_freq.append(22.0+1.500*i) + if option in('TOUT','MAXI','ACCE_SUR_VITE') : + # calcul du max des valeurs absolues + maxa_ac=__ac.abs().extreme()['max'][0][1] + maxa_vi=__vi.abs().extreme()['max'][0][1] + maxa_de=__de.abs().extreme()['max'][0][1] + l_table.append(_F(LISTE_R=maxa_ac,PARA='ACCE_MAX')) + l_table.append(_F(LISTE_R=maxa_vi,PARA='VITE_MAX')) + l_table.append(_F(LISTE_R=maxa_de,PARA='DEPL_MAX')) + l_table.append(_F(LISTE_R=maxa_ac/maxa_vi,PARA='ACCE_SUR_VITE')) + if option in('TOUT','INTE_ARIAS') : + __a2=__ac*__ac + inte_arias=__a2.trapeze(0.).vale_y[-1] + inte_arias=inte_arias*math.pi/NOCI_SEISME['PESANTEUR']/2. + l_table.append(_F(LISTE_R=inte_arias,PARA='INTE_ARIAS')) + if option in('TOUT','POUV_DEST') : + __v2=__vi*__vi + pouv_dest=__v2.trapeze(0.).vale_y[-1] + pouv_dest=pouv_dest*(math.pi)**3/NOCI_SEISME['PESANTEUR']/2. + l_table.append(_F(LISTE_R=pouv_dest,PARA='POUV_DEST')) + if option in('TOUT','VITE_ABSO_CUMU') : + __vc=__aa.trapeze(0.) + vite_abso=__vc.vale_y[-1] + l_table.append(_F(LISTE_R=vite_abso,PARA='VITE_ABSO_CUMU')) + if option in('TOUT','INTE_SPEC') : + amor=NOCI_SEISME['AMOR_REDUIT'] + fini=NOCI_SEISME['FREQ_INIT' ] + ffin=NOCI_SEISME['FREQ_FIN' ] + __so= CALC_FONCTION(SPEC_OSCI=_F( + NATURE ='VITE', + NATURE_FONC='ACCE', + FONCTION =NOCI_SEISME['FONCTION'], + METHODE ='NIGAM', + NORME =NOCI_SEISME['NORME'], + FREQ =l_freq, + AMOR_REDUIT=(amor,) + ), ) + __srov=__so.convert().l_fonc[0] + __srov=__srov.cut(fini,ffin,NOCI_SEISME['PRECISION'],NOCI_SEISME['CRITERE']) + __srov.vale_y=__srov.vale_y/__srov.vale_x/__srov.vale_x + insp=__srov.trapeze(0.).vale_y[-1] + l_table.append(_F(LISTE_R=fini ,PARA='FREQ_INIT' )) + l_table.append(_F(LISTE_R=ffin ,PARA='FREQ_FIN' )) + l_table.append(_F(LISTE_R=amor ,PARA='AMOR_REDUIT')) + l_table.append(_F(LISTE_R=insp ,PARA='INTE_SPECT' )) + if option in('TOUT','DUREE_PHAS_FORT') : + __a2=__ac*__ac + __i2=__a2.trapeze(0.) + arias = __i2.vale_y[-1]*math.pi/NOCI_SEISME['PESANTEUR']/2. + valinf = arias * NOCI_SEISME['BORNE_INF'] + valsup = arias * NOCI_SEISME['BORNE_SUP'] + for i in range(len(__i2.vale_x)) : + ariask = __i2.vale_y[i]*math.pi/NOCI_SEISME['PESANTEUR']/2. + if ariask>=valinf : break + for j in range(len(__i2.vale_x)-1,-1,-1) : + ariask = __i2.vale_y[j]*math.pi/NOCI_SEISME['PESANTEUR']/2. + if ariask<=valsup : break + dphfor = __i2.vale_x[j] - __i2.vale_x[i] + l_table.append(_F(LISTE_R=dphfor,PARA='DUREE_PHAS_FORT')) + C_out=CREA_TABLE(LISTE=l_table) + + return ier diff --git a/Aster/Cata/Macro/macr_ascouf_calc_ops.py b/Aster/Cata/Macro/macr_ascouf_calc_ops.py index fda98363..4c7c9b96 100644 --- a/Aster/Cata/Macro/macr_ascouf_calc_ops.py +++ b/Aster/Cata/Macro/macr_ascouf_calc_ops.py @@ -1,4 +1,4 @@ -#@ MODIF macr_ascouf_calc_ops Macro DATE 22/11/2004 AUTEUR LEBOUVIE F.LEBOUVIER +#@ MODIF macr_ascouf_calc_ops Macro DATE 08/02/2005 AUTEUR CIBHHLV L.VIVAN # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -358,6 +358,7 @@ def macr_ascouf_calc_ops(self,TYPE_MAILLAGE,CL_BOL_P2_GV,MAILLAGE,MODELE,CHAM_MA # l epaisseur # l_grno=MAILLAGE.LIST_GROUP_NO() + tabprl=[None]*4 tablig=[None]*4 # # prelevements des ligaments circonferentiels et longitudinaux @@ -370,15 +371,20 @@ def macr_ascouf_calc_ops(self,TYPE_MAILLAGE,CL_BOL_P2_GV,MAILLAGE,MODELE,CHAM_MA elif (tgrno[0][:4] in LIG) and (tgrno[0][4:6] not in ('GV','TU','MI')): lgrno.append(tgrno[0]) # motscles={} - motscles['SEGMENT']=[] - for grno in lgrno : motscles['SEGMENT'].append(_F(INTITULE=grno,GROUP_NO=grno)) + motscles['ACTION']=[] + for grno in lgrno : + motscles['ACTION'].append(_F(RESULTAT=nomres, + NOM_CHAM='SIEF_ELNO_ELGA', + TOUT_CMP='OUI', + INTITULE=grno, + GROUP_NO=grno, + OPERATION='EXTRACTION',)) motscles['TITRE']='TABLE DE POST-TRAITEMENT SECTION SOUS-EPAISSEUR' + tabprl[1]=POST_RELEVE_T(**motscles) tablig[1]=POST_RCCM(MATER = rccmat, - MAILLAGE = MAILLAGE, TYPE_RESU_MECA = 'EVOLUTION', OPTION = 'PM_PB', - TRANSITOIRE=_F(RESULTAT=nomres, - NOM_CHAM='SIEF_ELNO_ELGA',),**motscles) + TRANSITOIRE=_F(TABL_RESU_MECA = tabprl[1],),) # motscles={} motscles['ACTION']=[] @@ -436,6 +442,7 @@ def macr_ascouf_calc_ops(self,TYPE_MAILLAGE,CL_BOL_P2_GV,MAILLAGE,MODELE,CHAM_MA # les 8 ligaments sont tous les 45 degres # ACOUR = mc_IMPR_TABLE['ANGLE']*pi/180.0 + secprl=[None]*3 secrcm=[None]*3 secinv=[None]*3 secmoy=[None]*3 @@ -450,15 +457,21 @@ def macr_ascouf_calc_ops(self,TYPE_MAILLAGE,CL_BOL_P2_GV,MAILLAGE,MODELE,CHAM_MA # # moyenne RCCM sur les sections MI,TU et GV # - motscles['SEGMENT']=[] - for j in range(8) : motscles['SEGMENT'].append(_F(INTITULE=LIG[j]+SECT[i], - GROUP_NO=LIG[j]+SECT[i])) - secrcm[i] = POST_RCCM( MAILLAGE = MAILLAGE , - MATER = rccmat , - TYPE_RESU_MECA = 'EVOLUTION' , - OPTION = 'PM_PB' , - TRANSITOIRE = _F(RESULTAT = nomres,NOM_CHAM='SIEF_ELNO_ELGA'), - **motscles) + motscles={} + motscles['ACTION']=[] + for j in range(8) : + motscles['ACTION'].append(_F(RESULTAT=nomres, + NOM_CHAM='SIEF_ELNO_ELGA', + TOUT_CMP='OUI', + INTITULE=LIG[j]+SECT[i], + GROUP_NO=LIG[j]+SECT[i], + OPERATION='EXTRACTION',)) + motscles['TITRE']='TABLE DE POST-TRAITEMENT MOYENNE RCCM SECTION '+SECT[i] + secprl[i]=POST_RELEVE_T(**motscles) + secrcm[i]=POST_RCCM(MATER = rccmat, + TYPE_RESU_MECA = 'EVOLUTION', + OPTION = 'PM_PB', + TRANSITOIRE=_F(TABL_RESU_MECA = secprl[i],),) # # invariants sur les sections MI,TU et GV # diff --git a/Aster/Cata/Macro/macr_ascouf_mail_ops.py b/Aster/Cata/Macro/macr_ascouf_mail_ops.py index f7b95acf..fe02927a 100644 --- a/Aster/Cata/Macro/macr_ascouf_mail_ops.py +++ b/Aster/Cata/Macro/macr_ascouf_mail_ops.py @@ -1,4 +1,4 @@ -#@ MODIF macr_ascouf_mail_ops Macro DATE 30/11/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF macr_ascouf_mail_ops Macro DATE 09/05/2005 AUTEUR LEBOUVIE F.LEBOUVIER # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -2339,8 +2339,8 @@ def macr_ascouf_mail_ops(self,EXEC_MAILLAGE,TYPE_ELEM,COUDE, # coude fissure # if FISS_COUDE!=None: - if (RM/EP1)<5. or (RM/EP1)>12.: - print ' valeur hors domaine de validite (5,12)' + if (RM/EP1)<5. or (RM/EP1)>50.: + print ' valeur hors domaine de validite (5,50)' print ' rapport RM/EP1 :',(RM/EP1) self.cr.fatal(" erreur donnees ") ier = ier+1 diff --git a/Aster/Cata/Macro/macr_aspic_calc_ops.py b/Aster/Cata/Macro/macr_aspic_calc_ops.py index b6d91b36..5426c395 100644 --- a/Aster/Cata/Macro/macr_aspic_calc_ops.py +++ b/Aster/Cata/Macro/macr_aspic_calc_ops.py @@ -1,4 +1,4 @@ -#@ MODIF macr_aspic_calc_ops Macro DATE 22/11/2004 AUTEUR LEBOUVIE F.LEBOUVIER +#@ MODIF macr_aspic_calc_ops Macro DATE 08/02/2005 AUTEUR CIBHHLV L.VIVAN # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -427,18 +427,21 @@ def macr_aspic_calc_ops(self,TYPE_MAILLAGE,TUBULURE,MAILLAGE,MODELE,CHAM_MATER,C if i<10 : NUME = '0'+str(i) else : NUME = str(i) mcsimp={} - mcsimp['PRECISION']=55.E-1 - mcsimp['GROUP_NO' ]='LD'+str(i) + mcsimp['INTITULE' ]='LD'+str(i) + mcsimp['GROUP_NO' ]='LD'+str(i) + mcsimp['RESULTAT' ]=nomres + mcsimp['TOUT_ORDRE' ]='OUI' + mcsimp['NOM_CHAM' ]='SIEF_ELNO_ELGA' + mcsimp['PRECISION' ]=55.E-1 + mcsimp['TOUT_CMP' ]='OUI' + mcsimp['OPERATION' ]='EXTRACTION' mcfact.append( _F(**mcsimp) ) - __pmpbsd=POST_RCCM(MATER = MRCCM, - MAILLAGE = MAILLAGE, + __prelsd=POST_RELEVE_T(ACTION=mcfact) + __pmpbsd=POST_RCCM(OPTION = 'PM_PB', TYPE_RESU_MECA = 'EVOLUTION', - TYPE_RESU = 'VALE_MAX', - OPTION = 'PM_PB', - SEGMENT = mcfact, - TRANSITOIRE = _F(RESULTAT =nomres, - NOM_CHAM ='SIEF_ELNO_ELGA', - TOUT_ORDRE='OUI',), + TYPE_RESU = 'VALE_MAX', + MATER = MRCCM, + TRANSITOIRE = _F(TABL_RESU_MECA = __prelsd,), TITRE = '-- TRAITEMENT DES AZIMUTS DROITS --',) IMPR_TABLE(TABLE = __pmpbsd, ) # @@ -514,18 +517,21 @@ def macr_aspic_calc_ops(self,TYPE_MAILLAGE,TUBULURE,MAILLAGE,MODELE,CHAM_MATER,C if i<10 : NUME = '0'+str(i) else : NUME = str(i) mcsimp={} - mcsimp['PRECISION']=55.E-1 - mcsimp['GROUP_NO' ]='LI'+str(i) + mcsimp['INTITULE' ]='LI'+str(i) + mcsimp['GROUP_NO' ]='LI'+str(i) + mcsimp['RESULTAT' ]=nomres + mcsimp['TOUT_ORDRE' ]='OUI' + mcsimp['NOM_CHAM' ]='SIEF_ELNO_ELGA' + mcsimp['PRECISION' ]=55.E-1 + mcsimp['TOUT_CMP' ]='OUI' + mcsimp['OPERATION' ]='EXTRACTION' mcfact.append( _F(**mcsimp) ) - __pmpbsi=POST_RCCM(MATER = MRCCM, - MAILLAGE = MAILLAGE, + __prelsi=POST_RELEVE_T(ACTION=mcfact) + __pmpbsi=POST_RCCM(OPTION = 'PM_PB', TYPE_RESU_MECA = 'EVOLUTION', - TYPE_RESU = 'VALE_MAX', - OPTION = 'PM_PB', - SEGMENT = mcfact, - TRANSITOIRE = _F(RESULTAT =nomres, - NOM_CHAM ='SIEF_ELNO_ELGA', - TOUT_ORDRE='OUI',), + TYPE_RESU = 'VALE_MAX', + MATER = MRCCM, + TRANSITOIRE = _F(TABL_RESU_MECA = __prelsi,), TITRE = '-- TRAITEMENT DES AZIMUTS INCLINES --',) IMPR_TABLE(TABLE = __pmpbsi, ) # diff --git a/Aster/Cata/Macro/macr_cabri_mail_ops.py b/Aster/Cata/Macro/macr_cabri_mail_ops.py index d5ad388f..92154545 100644 --- a/Aster/Cata/Macro/macr_cabri_mail_ops.py +++ b/Aster/Cata/Macro/macr_cabri_mail_ops.py @@ -1,4 +1,4 @@ -#@ MODIF macr_cabri_mail_ops Macro DATE 14/09/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF macr_cabri_mail_ops Macro DATE 07/02/2005 AUTEUR MABBAS M.ABBAS # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -72,11 +72,11 @@ def macr_cabri_mail_ops(self,EXEC_MAILLAGE,RAFF_MAILLAGE,VERI_MAIL,GEOM_BRID, imp_formF = 1 else: imp_formF = 0 - if IMPRESSION['FICHIER']!=None: - imp_fich = IMPRESSION['FICHIER'] - imp_fichF = 1 - else: - imp_fichF = 0 +# if IMPRESSION['FICHIER']!=None: +# imp_fich = IMPRESSION['FICHIER'] +# imp_fichF = 1 +# else: +# imp_fichF = 0 # Maillage nrad = RAFF_MAILLAGE['NB_RADIAL'] @@ -141,8 +141,8 @@ def macr_cabri_mail_ops(self,EXEC_MAILLAGE,RAFF_MAILLAGE,VERI_MAIL,GEOM_BRID, nomres = LIRE_MAILLAGE(VERI_MAIL=_F(APLAT = ver_apla, VERIF = ver_veri ),) - if (imp_fichF == 1): - print imp_fich +# if (imp_fichF == 1): +# print imp_fich if (imp_formF == 1): print imp_form if (imp_unitF == 1): diff --git a/Aster/Cata/Macro/macr_fiab_impr_ops.py b/Aster/Cata/Macro/macr_fiab_impr_ops.py index 3b338c77..08ac8d10 100644 --- a/Aster/Cata/Macro/macr_fiab_impr_ops.py +++ b/Aster/Cata/Macro/macr_fiab_impr_ops.py @@ -1,4 +1,4 @@ -#@ MODIF macr_fiab_impr_ops Macro DATE 07/10/2004 AUTEUR GNICOLAS G.NICOLAS +#@ MODIF macr_fiab_impr_ops Macro DATE 24/01/2005 AUTEUR DURAND C.DURAND # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -17,8 +17,6 @@ # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, # 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. # ====================================================================== - - # RESPONSABLE GNICOLAS G.NICOLAS # def macr_fiab_impr_ops(self, INFO, @@ -86,14 +84,16 @@ def macr_fiab_impr_ops(self, INFO, # 5. Ecritures des gradients #____________________________________________________________________ # - for val in GRADIENTS : + if GRADIENTS is not None : # - IMPR_TABLE ( TABLE = val["TABLE"], - SENSIBILITE = val["PARA_SENSI"], - NOM_PARA = (val["NOM_PARA"]), - UNITE = Unite_Fichier_ASTER_vers_FIABILITE, - FORMAT_R = FORMAT_R, - INFO = INFO ) + for val in GRADIENTS : +# + IMPR_TABLE ( TABLE = val["TABLE"], + SENSIBILITE = val["PARA_SENSI"], + NOM_PARA = (val["NOM_PARA"]), + UNITE = Unite_Fichier_ASTER_vers_FIABILITE, + FORMAT_R = FORMAT_R, + INFO = INFO ) #____________________________________________________________________ # # 6. Libération du fichier d'échange diff --git a/Aster/Cata/Macro/macr_lign_coupe_ops.py b/Aster/Cata/Macro/macr_lign_coupe_ops.py index 0d57da06..107ec4a2 100644 --- a/Aster/Cata/Macro/macr_lign_coupe_ops.py +++ b/Aster/Cata/Macro/macr_lign_coupe_ops.py @@ -1,21 +1,21 @@ -#@ MODIF macr_lign_coupe_ops Macro DATE 14/09/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF macr_lign_coupe_ops Macro DATE 14/02/2005 AUTEUR DURAND C.DURAND # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG -# THIS PROGRAM 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 2 OF THE LICENSE, OR -# (AT YOUR OPTION) ANY LATER VERSION. -# -# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, -# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# THIS PROGRAM 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 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. # ====================================================================== @@ -23,81 +23,104 @@ ######################################################################## # script PYTHON de creation d un maillage de ligne de coupe -def crea_mail_lig_coup(lignes): +def crea_mail_lig_coup(dimension,lignes,groups): import os,sys,copy - try: # construction du maillage au format Aster des segments de lignes de coupe - nblig=len(lignes) - dimension=len(lignes[0][0]) + nblig=len(lignes) + nbngr=len(groups) - resu='TITRE\n' - titre='Maillage ligne de coupe'+'\n' - resu=resu+'FINSF\n' - resu=resu+'COOR_'+str(dimension)+'D\n' + resu='TITRE\n' + titre='Maillage ligne de coupe'+'\n' + resu=resu+'FINSF\n' + resu=resu+'COOR_'+str(dimension)+'D\n' # creation des noeuds - nbno=0 - for i in range(nblig): - pt1 = lignes[i][0] - pt2 = lignes[i][1] - nbp_lig_coupe = lignes[i][2] - for j in range(nbp_lig_coupe): - if dimension==2: - x=pt1[0]+j*(pt2[0]-pt1[0])/(nbp_lig_coupe-1) - y=pt1[1]+j*(pt2[1]-pt1[1])/(nbp_lig_coupe-1) - nbno=nbno+1 - noeud=' N'+str(nbno)+' '+str(x)+' '+str(y)+'\n' - resu=resu+noeud - elif dimension==3: - x=pt1[0]+j*(pt2[0]-pt1[0])/(nbp_lig_coupe-1) - y=pt1[1]+j*(pt2[1]-pt1[1])/(nbp_lig_coupe-1) - z=pt1[2]+j*(pt2[2]-pt1[2])/(nbp_lig_coupe-1) - nbno=nbno+1 - noeud=' N'+str(nbno)+' '+str(x)+' '+str(y)+' '+str(z)+'\n' - resu=resu+noeud - resu=resu+'FINSF\n' + nbno=0 + for i in range(nblig): + pt1 = lignes[i][0] + pt2 = lignes[i][1] + nbp_lig_coupe = lignes[i][2] + for j in range(nbp_lig_coupe): + if dimension==2: + x=pt1[0]+j*(pt2[0]-pt1[0])/(nbp_lig_coupe-1) + y=pt1[1]+j*(pt2[1]-pt1[1])/(nbp_lig_coupe-1) + nbno=nbno+1 + noeud=' N'+str(nbno)+' '+str(x)+' '+str(y)+'\n' + resu=resu+noeud + elif dimension==3: + x=pt1[0]+j*(pt2[0]-pt1[0])/(nbp_lig_coupe-1) + y=pt1[1]+j*(pt2[1]-pt1[1])/(nbp_lig_coupe-1) + z=pt1[2]+j*(pt2[2]-pt1[2])/(nbp_lig_coupe-1) + nbno=nbno+1 + noeud=' N'+str(nbno)+' '+str(x)+' '+str(y)+' '+str(z)+'\n' + resu=resu+noeud + for i in range(nbngr): + for pt in groups[i][1:]: + if dimension==2: + nbno=nbno+1 + noeud=' N'+str(nbno)+' '+str(pt[0])+' '+str(pt[1])+'\n' + resu=resu+noeud + elif dimension==3: + nbno=nbno+1 + noeud=' N'+str(nbno)+' '+str(pt[0])+' '+str(pt[1])+' '+str(pt[2])+'\n' + resu=resu+noeud + resu=resu+'FINSF\n' # creation des mailles - nbma=0 - for i in range(nblig): - nbp_lig_coupe = lignes[i][2] - resu=resu+'SEG2\n' - for j in range(nbp_lig_coupe-1): - nbma=nbma+1 - maille=' M'+str(nbma)+' N'+str(nbma+i)+' N'+str(nbma+1+i)+'\n' - resu=resu+maille - resu=resu+'FINSF\n' + nbma=0 + for i in range(nblig): + nbp_lig_coupe = lignes[i][2] + resu=resu+'SEG2\n' + for j in range(nbp_lig_coupe-1): + nbma=nbma+1 + maille=' M'+str(nbma)+' N'+str(nbma+i)+' N'+str(nbma+1+i)+'\n' + resu=resu+maille + resu=resu+'FINSF\n' + for i in range(nbngr): + resu=resu+'SEG2\n' + for pt in groups[i][1:-1]: + nbma=nbma+1 + maille=' M'+str(nbma)+' N'+str(nbma+nblig+i)+' N'+str(nbma+nblig+1+i)+'\n' + resu=resu+maille + resu=resu+'FINSF\n' # creation des groupes de mailles (1 par ligne de coupe) - nbma=0 - for i in range(nblig): - resu=resu+'GROUP_MA\n' - resu=resu+' LICOU'+str(i+1) - nbp_lig_coupe = lignes[i][2] - for j in range(nbp_lig_coupe-1): - nbma=nbma+1 - resu=resu+' M'+str(nbma)+'\n' - resu=resu+'\n' - resu=resu+'FINSF\n' - resu=resu+'FIN\n' - - return resu - - except : - return 0 + nbma=0 + for i in range(nblig): + resu=resu+'GROUP_MA\n' + resu=resu+' LICOU'+str(i+1) + nbp_lig_coupe = lignes[i][2] + for j in range(nbp_lig_coupe-1): + nbma=nbma+1 + resu=resu+' M'+str(nbma)+'\n' + resu=resu+'\n' + resu=resu+'FINSF\n' + for i in range(nbngr): + resu=resu+'GROUP_MA\n' + resu=resu+groups[i][0] + nbp_lig_coupe = len(groups[i])-1 + for j in range(nbp_lig_coupe-1): + nbma=nbma+1 + resu=resu+' M'+str(nbma)+'\n' + resu=resu+'\n' + resu=resu+'FINSF\n' + resu=resu+'FIN\n' + + return resu + ######################################################################## -def macr_lign_coupe_ops(self,RESULTAT,UNITE_MAILLAGE,LIGN_COUPE,MODELE, - NOM_CHAM,**args): +def macr_lign_coupe_ops(self,RESULTAT,UNITE_MAILLAGE,LIGN_COUPE,NOM_CHAM,MODELE,**args): """ Ecriture de la macro MACR_LIGN_COUPE """ - import os + import os,string,types from Accas import _F from Noyau.N_utils import AsType + import aster ier=0 # On importe les definitions des commandes a utiliser dans la macro @@ -106,20 +129,57 @@ def macr_lign_coupe_ops(self,RESULTAT,UNITE_MAILLAGE,LIGN_COUPE,MODELE, AFFE_MODELE =self.get_cmd('AFFE_MODELE') PROJ_CHAMP =self.get_cmd('PROJ_CHAMP') POST_RELEVE_T =self.get_cmd('POST_RELEVE_T') + CREA_TABLE =self.get_cmd('CREA_TABLE') # La macro compte pour 1 dans la numerotation des commandes #self.icmd=1 self.set_icmd(1) + + nomresu=RESULTAT.nom + l_modele=aster.getvectjev(nomresu.ljust(19)+'.MODL') + n_modele=string.strip(l_modele[0]) + if n_modele=='' : + if MODELE==None: + ier=ier+1 + self.cr.fatal(" nom du modele absent dans le concept resultat "+nomresu) + return ier + else : n_modele=MODELE.nom + l_mailla=aster.getvectjev(n_modele.ljust(8)+'.MODELE .NOMA') + n_mailla=string.strip(l_mailla[0]) + dime=aster.getvectjev(n_mailla.ljust(8)+'.DIME')[5] + collgrno=aster.getcolljev(n_mailla.ljust(8)+'.GROUPENO') lignes=[] + groups=[] + minidim=dime for m in LIGN_COUPE : - lignes.append((m['COOR_ORIG'],m['COOR_EXTR'],m['NB_POINTS'])) + if m['NB_POINTS'] !=None : + lignes.append((m['COOR_ORIG'],m['COOR_EXTR'],m['NB_POINTS'])) + minidim=min(minidim,len(m['COOR_ORIG']),len(m['COOR_EXTR'])) + elif m['GROUP_NO']!=None : + ngrno=m['GROUP_NO'].ljust(8).upper() + if ngrno not in collgrno.keys() : + ier=ier+1 + self.cr.fatal(" le group_no "+ngrno+" n est pas dans le maillage "+n_mailla) + return ier + grpn=collgrno[ngrno] + l_coor_group=[ngrno,] + for node in grpn: + l_coor_group.append(aster.getvectjev(n_mailla.ljust(8)+'.COORDO .VALE',3*(node-1),3)) + groups.append(l_coor_group) + + if minidim!=dime: + ier=ier+1 + self.cr.fatal(" dimensions de maillage et de coordonnees incoherentes") + return ier + # Création du maillage des NB_POINTS segments entre COOR_ORIG et COOR_EXTR + # ainsi que des segments reliant les noeuds issus des group_no demandés # par appel au script python crea_mail_lig_coup # le maillage est ensuite recopié dans l unité logique UNITE_MAILLAGE - resu_mail=crea_mail_lig_coup(lignes) + resu_mail=crea_mail_lig_coup(dime,lignes,groups) cur_dir=os.getcwd() nomFichierSortie =cur_dir+'/fort.'+str(UNITE_MAILLAGE) fproc=open(nomFichierSortie,'w') @@ -134,8 +194,11 @@ def macr_lign_coupe_ops(self,RESULTAT,UNITE_MAILLAGE,LIGN_COUPE,MODELE, iocc=1 motscles['CREA_GROUP_NO']=[] for m in LIGN_COUPE : - motscles['CREA_GROUP_NO'].append(_F(GROUP_MA='LICOU'+str(iocc),) ) - iocc=iocc+1 + if m['NB_POINTS'] !=None : + motscles['CREA_GROUP_NO'].append(_F(GROUP_MA='LICOU'+str(iocc),) ) + iocc=iocc+1 + elif m['GROUP_NO']!=None : + motscles['CREA_GROUP_NO'].append(_F(GROUP_MA=m['GROUP_NO'].ljust(8).upper(),) ) __macou=DEFI_GROUP( reuse =__macou , MAILLAGE=__macou , **motscles ); if AsType(RESULTAT).__name__ in ('evol_elas','evol_noli') : @@ -151,23 +214,52 @@ def macr_lign_coupe_ops(self,RESULTAT,UNITE_MAILLAGE,LIGN_COUPE,MODELE, __recou=PROJ_CHAMP(METHODE='ELEM', RESULTAT=RESULTAT, - MODELE_1=MODELE, + MODELE_1=self.jdc.current_context[n_modele], MODELE_2=__mocou, + TYPE_CHAM='NOEU', NOM_CHAM=NOM_CHAM,); - # Production d'une table par ligne de coupe - # Toutes les tables sont des concepts sortant de la macro définies - # dans chaque occurence du mcfact lign_coupe + # Production d'une table pour toutes les lignes de coupe - iocc=1 + ioc2=0 + mcACTION=[] for m in LIGN_COUPE : - self.DeclareOut('tt',m['TABLE']) - tt=POST_RELEVE_T(ACTION=_F(INTITULE = 'lig.coupe'+str(iocc), - RESULTAT = __recou, - GROUP_NO = 'LICOU'+str(iocc), - NOM_CHAM = NOM_CHAM, - TOUT_CMP = 'OUI', - OPERATION = 'EXTRACTION', ),); - iocc=iocc+1 + if m['NB_POINTS'] !=None : + ioc2=ioc2+1 + groupe='LICOU'+str(ioc2) + if m['INTITULE'] !=None : intitl=m['INTITULE'] + else : intitl='l.coupe'+str(ioc2) + elif m['GROUP_NO']!=None : + groupe=m['GROUP_NO'].ljust(8).upper() + if m['INTITULE'] !=None : intitl=m['INTITULE'] + else : intitl=groupe + mcACTION.append( _F(INTITULE = intitl, + RESULTAT = __recou, + GROUP_NO = groupe, + NOM_CHAM = NOM_CHAM, + TOUT_CMP = 'OUI', + OPERATION = 'EXTRACTION', ) ) + + __tabitm=POST_RELEVE_T(ACTION=mcACTION,); + + # on repasse par les tables python pour supprimer les paramètres inutiles + # NOEUD (car il est propre au maillage de la ligne) et RESU + + self.DeclareOut('nomres',self.sd) + dictab=__tabitm.EXTR_TABLE() + listpara=dictab.para + listpara.remove('NOEUD') + listpara.remove('RESU') + + coltab=[] + for key in listpara : + val=dictab[key].values()[key] + if type(val[0])==types.IntType : + coltab.append(_F(PARA=key,LISTE_I=val)) + elif type(val[0])==types.FloatType : + coltab.append(_F(PARA=key,LISTE_R=val)) + elif type(val[0])==types.StringType : + coltab.append(_F(PARA=key,LISTE_K=val,TYPE_K='K16')) + nomres=CREA_TABLE(LISTE=coltab) return ier diff --git a/Aster/Cata/Macro/macr_recal_ops.py b/Aster/Cata/Macro/macr_recal_ops.py index 308846a5..17597e90 100644 --- a/Aster/Cata/Macro/macr_recal_ops.py +++ b/Aster/Cata/Macro/macr_recal_ops.py @@ -1,4 +1,4 @@ -#@ MODIF macr_recal_ops Macro DATE 14/09/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF macr_recal_ops Macro DATE 14/03/2005 AUTEUR DURAND C.DURAND # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -45,7 +45,7 @@ def macr_recal_ops(self,UNITE_ESCL, RESU_EXP, POIDS, LIST_PARA, RESU_CALC, import Macro from Cata import cata from Cata.cata import DEFI_LIST_REEL - from Macro.recal import gestion,transforme_list_Num,EXTRACT,calcul_F,graphique + from Macro.recal import gestion,transforme_list_Num,calcul_F,graphique from Macro import reca_message from Macro import reca_algo from Macro import reca_interp @@ -82,7 +82,6 @@ def macr_recal_ops(self,UNITE_ESCL, RESU_EXP, POIDS, LIST_PARA, RESU_CALC, if v.__class__.__name__ in ('OPER','MACRO'): self.current_context[k]= v self.current_context['_F']=cata.__dict__['_F'] - self.g_context['EXTRACT']=EXTRACT #_____________________________________________ # diff --git a/Aster/Cata/Macro/macro_cara_poutre_ops.py b/Aster/Cata/Macro/macro_cara_poutre_ops.py deleted file mode 100644 index a98d3d6f..00000000 --- a/Aster/Cata/Macro/macro_cara_poutre_ops.py +++ /dev/null @@ -1,684 +0,0 @@ -# -*- coding: utf-8 -*- -#@ MODIF macro_cara_poutre_ops Macro DATE 25/06/2002 AUTEUR JMBHH01 J.M.PROIX -# CONFIGURATION MANAGEMENT OF EDF VERSION -# ====================================================================== -# COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG -# THIS PROGRAM 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 2 OF THE LICENSE, OR -# (AT YOUR OPTION) ANY LATER VERSION. -# -# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, -# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. -# ====================================================================== -# RESPONSABLE JMBHH01 J.M.PROIX -def macro_cara_poutre_ops(self,UNITE_MAILLAGE,SYME_X,SYME_Y,GROUP_MA_BORD, - GROUP_MA,ORIG_INER,NOEUD,GROUP_MA_INTE, - LONGUEUR,MATERIAU,LIAISON, - **args): - """ - Ecriture de la macro MACRO_CARA_POUTRE - """ - import types - from Accas import _F - ier=0 - # On importe les definitions des commandes a utiliser dans la macro - # Le nom de la variable doit etre obligatoirement le nom de la commande - LIRE_MAILLAGE =self.get_cmd('LIRE_MAILLAGE') - DEFI_GROUP =self.get_cmd('DEFI_GROUP') - CREA_MAILLAGE =self.get_cmd('CREA_MAILLAGE') - AFFE_MODELE =self.get_cmd('AFFE_MODELE') - DEFI_MATERIAU =self.get_cmd('DEFI_MATERIAU') - AFFE_MATERIAU =self.get_cmd('AFFE_MATERIAU') - DEFI_FONCTION =self.get_cmd('DEFI_FONCTION') - DEFI_CONSTANTE =self.get_cmd('DEFI_CONSTANTE') - AFFE_CHAR_THER =self.get_cmd('AFFE_CHAR_THER') - AFFE_CHAR_THER_F=self.get_cmd('AFFE_CHAR_THER_F') - THER_LINEAIRE =self.get_cmd('THER_LINEAIRE') - CALC_VECT_ELEM =self.get_cmd('CALC_VECT_ELEM') - CALC_MATR_ELEM =self.get_cmd('CALC_MATR_ELEM') - NUME_DDL =self.get_cmd('NUME_DDL') - ASSE_VECTEUR =self.get_cmd('ASSE_VECTEUR') - POST_ELEM =self.get_cmd('POST_ELEM') - # La macro compte pour 1 dans la numerotation des commandes - self.icmd=1 - - # Le concept sortant (de type tabl_cara_geom) est nommé 'nomres' dans - # le contexte de la macro - - self.DeclareOut('nomres',self.sd) - - if GROUP_MA_BORD and GROUP_MA: - if not LIAISON: - ier=ier+1 - self.cr.fatal("Avec GROUP_MA, il faut obligatoirement preciser LIAISON, LONGUEUR ET MATERIAU") - return ier - - __nomlma=LIRE_MAILLAGE(UNITE=UNITE_MAILLAGE,) - - __nomamo=AFFE_MODELE(MAILLAGE=__nomlma, - AFFE=_F(TOUT='OUI', - PHENOMENE='MECANIQUE', - MODELISATION='D_PLAN',), ) - - __nomdma=DEFI_MATERIAU(ELAS=_F(E=1.0,NU=0.,RHO=1.0),) - - - __nomama=AFFE_MATERIAU(MAILLAGE=__nomlma, - AFFE=_F(TOUT='OUI', - MATER=__nomdma,), ) - -# --- CALCUL DES CARACTERISTIQUES GEOMETRIQUES DE LA SECTION : -# ------------------------------------------------------ - - motsimps={} - if GROUP_MA : motsimps['GROUP_MA'] = GROUP_MA - if SYME_X : motsimps['SYME_X'] = SYME_X - if SYME_Y : motsimps['SYME_Y'] = SYME_Y - motsimps['ORIG_INER'] = ORIG_INER - mfact=_F(TOUT='OUI',**motsimps) - nomres=POST_ELEM(MODELE=__nomamo, - CHAM_MATER=__nomama, - CARA_GEOM=mfact ) - -# nb : si GROUP_MA n existe pas : le mot clé est ignoré - -# -# ================================================================== -# --- = CALCUL DE LA CONSTANTE DE TORSION SUR TOUT LE MAILLAGE = -# --- = OU DU CENTRE DE TORSION/CISAILLEMENT = -# --- = DES COEFFICIENTS DE CISAILLEMENT = -# --- = ET DE L INERTIE DE GAUCHISSEMENT = -# --- = ON CREE UN MODELE PLAN 2D THERMIQUE REPRESENTANT LA SECTION = -# --- = DE LA POUTRE CAR ON A A RESOUDRE DES E.D.P. AVEC DES LAPLACIENS= -# ================================================================== - - if GROUP_MA_BORD and not GROUP_MA: - -# --- TRANSFORMATION DES GROUP_MA EN GROUP_NO SUR-LESQUELS -# --- ON POURRA APPLIQUER DES CONDITIONS DE TEMPERATURE IMPOSEE : -# --------------------------------------------------------- - motscles={} - if type(GROUP_MA_BORD)==types.StringType: - motscles['CREA_GROUP_NO']=_F(GROUP_MA=GROUP_MA_BORD,) - else: - motscles['CREA_GROUP_NO']=[] - for grma in GROUP_MA_BORD: - motscles['CREA_GROUP_NO'].append(_F(GROUP_MA=grma,)) - __nomlma=DEFI_GROUP(reuse=__nomlma, - MAILLAGE=__nomlma, - **motscles) - - -# --- CREATION D UN MAILLAGE IDENTIQUE AU PREMIER A CECI PRES -# --- QUE LES COORDONNEES SONT EXPRIMEES DANS LE REPERE PRINCIPAL -# --- D INERTIE DONT L ORIGINE EST LE CENTRE DE GRAVITE DE LA SECTION : -# --------------------------------------------------------------- - - __nomapi=CREA_MAILLAGE(MAILLAGE=__nomlma, - REPERE=_F(TABLE=nomres, - NOM_ORIG='CDG', ), ) - -# --- AFFECTATION DU PHENOMENE 'THERMIQUE' AU MODELE EN VUE DE -# --- LA CONSTRUCTION D UN OPERATEUR LAPLACIEN SUR CE MODELE : -# ------------------------------------------------------ - - __nomoth=AFFE_MODELE(MAILLAGE=__nomapi, - AFFE=_F(TOUT='OUI', - PHENOMENE='THERMIQUE', - MODELISATION='PLAN',), ) - -# --- POUR LA CONSTRUCTION DU LAPLACIEN, ON DEFINIT UN -# --- PSEUDO-MATERIAU DONT LES CARACTERISTIQUES THERMIQUES SONT : -# --- LAMBDA = 1, RHO*CP = 0 : -# ---------------------- - - __nomath=DEFI_MATERIAU(THER=_F(LAMBDA=1.0,RHO_CP=0.,),) - -# --- DEFINITION D UN CHAM_MATER A PARTIR DU MATERIAU PRECEDENT : -# --------------------------------------------------------- - - __chmath=AFFE_MATERIAU(MAILLAGE=__nomapi, - AFFE=_F(TOUT='OUI', - MATER=__nomath,), ) - -# -# ------------------------------------------------------------ -# --- - CALCUL DE LA CONSTANTE DE TORSION PAR RESOLUTION - -# --- - D UN LAPLACIEN AVEC UN TERME SOURCE EGAL A -2 - -# --- - L INCONNUE ETANT NULLE SUR LE CONTOUR DE LA SECTION : - -# --- - LAPLACIEN(PHI) = -2 DANS LA SECTION - -# --- - PHI = 0 SUR LE CONTOUR : - -# ------------------------------------------------------------ -# -# --- ON IMPOSE LA VALEUR 0 A L INCONNUE SCALAIRE SUR LE CONTOUR -# --- DE LA SECTION -# --- ET ON A UN TERME SOURCE EGAL A -2 DANS TOUTE LA SECTION : -# ------------------------------------------------------- - - motscles={} - if GROUP_MA_INTE: - motscles['LIAISON_UNIF']=_F(GROUP_MA=GROUP_MA_INTE,DDL='TEMP'), - __chart1=AFFE_CHAR_THER(MODELE=__nomoth, - TEMP_IMPO =_F(GROUP_NO=GROUP_MA_BORD, - TEMP=0. ), - SOURCE =_F(TOUT='OUI', - SOUR=2.0), - **motscles ) - -# --- POUR CHAQUE TROU DE LA SECTION : -# --- .ON A IMPOSE QUE PHI EST CONSTANT SUR LE CONTOUR INTERIEUR -# --- EN FAISANT LE LIAISON_UNIF DANS LE AFFE_CHAR_THER PRECEDENT -# --- .ON IMPOSE EN PLUS D(PHI)/DN = 2*AIRE(TROU)/L(TROU) -# --- OU D/DN DESIGNE LA DERIVEE PAR RAPPORT A LA -# --- NORMALE ET L DESIGNE LA LONGUEUR DU BORD DU TROU : -# ------------------------------------------------------- - - if GROUP_MA_INTE: - __tbaire=POST_ELEM(MODELE=__nomoth, - AIRE_INTERNE=_F(GROUP_MA_BORD=GROUP_MA_INTE,), ) - - motscles={} - motscles['FLUX_REP']=[] - if type(GROUP_MA_INTE)==types.StringType: - motscles['FLUX_REP']=_F(GROUP_MA=GROUP_MA_INTE,CARA_TORSION=__tbaire) - else: - motscles['FLUX_REP']=[] - for grma in GROUP_MA_INTE: - motscles['FLUX_REP'].append(_F(GROUP_MA=grma,CARA_TORSION=__tbaire),) - __chart2=AFFE_CHAR_THER(MODELE=__nomoth,**motscles) - -# --- RESOLUTION DE LAPLACIEN(PHI) = -2 -# --- AVEC PHI = 0 SUR LE CONTOUR : -# ---------------------------------------- - - motscles={} - motscles['EXCIT']=[_F(CHARGE=__chart1,),] - if GROUP_MA_INTE: - motscles['EXCIT'].append(_F(CHARGE=__chart2,)) - __tempe1=THER_LINEAIRE(MODELE=__nomoth, - CHAM_MATER=__chmath, - SOLVEUR=_F(STOP_SINGULIER='NON',), - **motscles ) - -# -# ---------------------------------------------- -# --- - CALCUL DU CENTRE DE TORSION/CISAILLEMENT - -# --- - ET DES COEFFICIENTS DE CISAILLEMENT : - -# ---------------------------------------------- -# -# --- POUR LE CALCUL DES CONSTANTES DE CISAILLEMENT, ON VA DEFINIR -# --- UN PREMIER TERME SOURCE, SECOND MEMBRE DE L EQUATION DE LAPLACE -# --- PAR UNE FONCTION EGALE A Y : -# -------------------------- - - __fnsec1=DEFI_FONCTION(NOM_PARA='X', - VALE=(0.,0.,10.,10.), - PROL_DROITE='LINEAIRE', - PROL_GAUCHE='LINEAIRE', - ) - - __fnsec0=DEFI_CONSTANTE(VALE=0.,) - -# --- LE TERME SOURCE CONSTITUANT LE SECOND MEMBRE DE L EQUATION -# --- DE LAPLACE EST PRIS EGAL A Y DANS TOUTE LA SECTION : -# -------------------------------------------------- - - - motscles={} - if NOEUD: - motscles['TEMP_IMPO']=(_F(NOEUD=NOEUD,TEMP=__fnsec0)) - __chart2=AFFE_CHAR_THER_F(MODELE=__nomoth, - SOURCE=_F(TOUT='OUI', - SOUR=__fnsec1,), - **motscles ) - -# --- RESOLUTION DE LAPLACIEN(PHI) = -Y -# --- AVEC D(PHI)/D(N) = 0 SUR LE CONTOUR : -# ------------------------------------------------ - - __tempe2=THER_LINEAIRE(MODELE=__nomoth, - CHAM_MATER=__chmath, - EXCIT=_F(CHARGE=__chart2,), - SOLVEUR=_F(STOP_SINGULIER='NON',), - ) - -# --- POUR LE CALCUL DES CONSTANTES DE CISAILLEMENT, ON VA DEFINIR -# --- UN PREMIER TERME SOURCE, SECOND MEMBRE DE L EQUATION DE LAPLACE -# --- PAR UNE FONCTION EGALE A Z : -# -------------------------- - - __fnsec2=DEFI_FONCTION(NOM_PARA='Y', - VALE=(0.,0.,10.,10.), - PROL_DROITE='LINEAIRE', - PROL_GAUCHE='LINEAIRE', - ) - -# --- LE TERME SOURCE CONSTITUANT LE SECOND MEMBRE DE L EQUATION -# --- DE LAPLACE EST PRIS EGAL A Z DANS TOUTE LA SECTION : -# -------------------------------------------------- - - motscles={} - if NOEUD: - motscles['TEMP_IMPO']=_F(NOEUD=NOEUD,TEMP=__fnsec0) - __chart3=AFFE_CHAR_THER_F(MODELE=__nomoth, - SOURCE=_F(TOUT='OUI', - SOUR=__fnsec2,), - **motscles) - -# --- RESOLUTION DE LAPLACIEN(PHI) = -Z -# --- AVEC D(PHI)/D(N) = 0 SUR LE CONTOUR : -# ------------------------------------------------ - - __tempe3=THER_LINEAIRE(MODELE=__nomoth, - CHAM_MATER=__chmath, - EXCIT=_F(CHARGE=__chart3,), - SOLVEUR=_F(STOP_SINGULIER='NON',), - ) - -# --- CALCUL DE LA CONSTANTE DE TORSION : -# --------------------------------- - - motscles={} - if GROUP_MA_INTE: - motscles['CARA_POUTRE']=_F(CARA_GEOM=nomres, - LAPL_PHI=__tempe1, - TOUT='OUI', - OPTION='CARA_TORSION', - GROUP_MA_INTE=GROUP_MA_INTE,) - else: - motscles['CARA_POUTRE']=_F(CARA_GEOM=nomres, - LAPL_PHI=__tempe1, - TOUT='OUI', - OPTION='CARA_TORSION', ) - nomres=POST_ELEM(reuse=nomres, - MODELE=__nomoth, - CHAM_MATER=__chmath, - **motscles ) - -# --- CALCUL DES COEFFICIENTS DE CISAILLEMENT ET DES COORDONNEES DU -# --- CENTRE DE CISAILLEMENT/TORSION : -# ------------------------------ - - nomres=POST_ELEM(reuse=nomres, - MODELE=__nomoth, - CHAM_MATER=__chmath, - CARA_POUTRE=_F(CARA_GEOM=nomres, - LAPL_PHI_Y=__tempe2, - LAPL_PHI_Z=__tempe3, - TOUT='OUI', - OPTION='CARA_CISAILLEMENT',), ) - -# -# ------------------------------------------------------------ -# --- - CALCUL DE L INERTIE DE GAUCHISSEMENT PAR RESOLUTION DE - -# --- - LAPLACIEN(OMEGA) = 0 DANS LA SECTION - -# --- - AVEC D(OMEGA)/D(N) = Z*NY-Y*NZ SUR LE - -# --- - CONTOUR DE LA SECTION - -# --- - NY ET NZ SONT LES COMPOSANTES DU VECTEUR N NORMAL - -# --- - A CE CONTOUR - -# --- - ET SOMME_S(OMEGA.DS) = 0 - -# --- - OMEGA EST LA FONCTION DE GAUCHISSEMENT - -# --- - L INERTIE DE GAUCHISSEMENT EST SOMME_S(OMEGA**2.DS) - -# ------------------------------------------------------------ -# -# --- CREATION D UN MAILLAGE DONT LES COORDONNEES SONT EXPRIMEES -# --- DANS LE REPERE PRINCIPAL D INERTIE MAIS AVEC COMME ORIGINE -# --- LE CENTRE DE TORSION DE LA SECTION, ON VA DONC UTILISER -# --- LE MAILLAGE DE NOM NOMAPI DONT LES COORDONNEES SONT -# --- EXPRIMEES DANS LE REPERE PRINCIPAL D'INERTIE, L'ORIGINE -# --- ETANT LE CENTRE DE GRAVITE DE LA SECTION (QUI EST DONC -# --- A CHANGER) : -# ---------- - - __nomapt=CREA_MAILLAGE(MAILLAGE=__nomapi, - REPERE=_F(TABLE=nomres, - NOM_ORIG='TORSION',) ) - -# --- AFFECTATION DU PHENOMENE 'THERMIQUE' AU MODELE EN VUE DE -# --- LA CONSTRUCTION D UN OPERATEUR LAPLACIEN SUR CE MODELE : -# ------------------------------------------------------ - - __nomot2=AFFE_MODELE(MAILLAGE=__nomapt, - AFFE=_F(TOUT='OUI', - PHENOMENE='THERMIQUE', - MODELISATION='PLAN', ) ) - -# --- DEFINITION D UN CHAM_MATER A PARTIR DU MATERIAU PRECEDENT : -# --------------------------------------------------------- - - __chmat2=AFFE_MATERIAU(MAILLAGE=__nomapt, - AFFE=_F(TOUT='OUI', - MATER=__nomath, ), ) - -# --- POUR LE CALCUL DE L INERTIE DE GAUCHISSEMENT, ON VA DEFINIR -# --- LA COMPOSANTE SELON Y DU FLUX A IMPOSER SUR LE CONTOUR -# --- PAR UNE FONCTION EGALE A -X : -# --------------------------- - - __fnsec3=DEFI_FONCTION(NOM_PARA='X', - VALE=(0.,0.,10.,-10.), - PROL_DROITE='LINEAIRE', - PROL_GAUCHE='LINEAIRE', - ) - -# --- POUR LE CALCUL DE L INERTIE DE GAUCHISSEMENT, ON VA DEFINIR -# --- LA COMPOSANTE SELON X DU FLUX A IMPOSER SUR LE CONTOUR -# --- PAR UNE FONCTION EGALE A Y : -# -------------------------- - - __fnsec4=DEFI_FONCTION(NOM_PARA='Y', - VALE=(0.,0.,10.,10.), - PROL_DROITE='LINEAIRE', - PROL_GAUCHE='LINEAIRE', - ) - -# --- DANS LE BUT D IMPOSER LA RELATION LINEAIRE ENTRE DDLS -# --- SOMME_SECTION(OMEGA.DS) = 0 ( CETTE CONDITION -# --- VENANT DE L EQUATION D EQUILIBRE SELON L AXE DE LA POUTRE -# --- N = 0, N ETANT L EFFORT NORMAL) -# --- ON CALCULE LE VECTEUR DE CHARGEMENT DU A UN TERME SOURCE EGAL -# --- A 1., LES TERMES DE CE VECTEUR SONT EGAUX A -# --- SOMME_SECTION(NI.DS) ET SONT DONC LES COEFFICIENTS DE -# --- LA RELATION LINEAIRE A IMPOSER. -# --- ON DEFINIT DONC UN CHARGEMENT DU A UN TERME SOURCE EGAL A 1 : -# ----------------------------------------------------------- - - __chart4=AFFE_CHAR_THER(MODELE=__nomot2, - SOURCE=_F(TOUT='OUI', - SOUR=1.0), ) - -# --- ON CALCULE LE VECT_ELEM DU AU CHARGEMENT PRECEDENT -# --- IL S AGIT DES VECTEURS ELEMENTAIRES DONT LE TERME -# --- AU NOEUD COURANT I EST EGAL A SOMME_SECTION(NI.DS) : -# -------------------------------------------------- - - __vecel=CALC_VECT_ELEM(CHARGE=__chart4, - OPTION='CHAR_THER' - ) - -# --- ON CALCULE LE MATR_ELEM DES MATRICES ELEMENTAIRES -# --- DE CONDUCTIVITE UNIQUEMENT POUR GENERER LE NUME_DDL -# --- SUR-LEQUEL S APPUIERA LE CHAMNO UTILISE POUR ECRIRE LA -# --- RELATION LINEAIRE ENTRE DDLS : -# ---------------------------- - - __matel=CALC_MATR_ELEM(MODELE=__nomot2, - CHAM_MATER=__chmat2, - CHARGE=__chart4, - OPTION='RIGI_THER',) - -# --- ON DEFINIT LE NUME_DDL ASSOCIE AU MATR_ELEM DEFINI -# --- PRECEDEMMENT POUR CONSTRUIRE LE CHAMNO UTILISE POUR ECRIRE LA -# --- RELATION LINEAIRE ENTRE DDLS : -# ---------------------------- - - __numddl=NUME_DDL(MATR_RIGI=__matel, - METHODE='LDLT', ) - -# --- ON CONSTRUIT LE CHAMNO QUI VA ETRE UTILISE POUR ECRIRE LA -# --- RELATION LINEAIRE ENTRE DDLS : -# ---------------------------- - - __chamno=ASSE_VECTEUR(VECT_ELEM=__vecel, - NUME_DDL=__numddl, ) - -# --- ON IMPOSE LA RELATION LINEAIRE ENTRE DDLS -# --- SOMME_SECTION(OMEGA.DS) = 0 ( CETTE CONDITION -# --- VENANT DE L EQUATION D EQUILIBRE SELON L AXE DE LA POUTRE -# --- N = 0, N ETANT L EFFORT NORMAL) -# --- POUR IMPOSER CETTE RELATION ON PASSE PAR LIAISON_CHAMNO, -# --- LES TERMES DU CHAMNO (I.E. SOMME_SECTION(NI.DS)) -# --- SONT LES COEFFICIENTS DE LA RELATION LINEAIRE : -# --------------------------------------------- - - __chart5=AFFE_CHAR_THER(MODELE=__nomot2, - LIAISON_CHAMNO=_F(CHAM_NO=__chamno, - COEF_IMPO=0.), ) - -# --- LE CHARGEMENT EST UN FLUX REPARTI NORMAL AU CONTOUR -# --- DONT LES COMPOSANTES SONT +Z (I.E. +Y) ET -Y (I.E. -X) -# --- SELON LA DIRECTION NORMALE AU CONTOUR : -# ------------------------------------- - - __chart6=AFFE_CHAR_THER_F(MODELE=__nomot2, - FLUX_REP=_F(GROUP_MA=GROUP_MA_BORD, - FLUX_X =__fnsec4, - FLUX_Y =__fnsec3,), ) - -# --- RESOLUTION DE LAPLACIEN(OMEGA) = 0 -# --- AVEC D(OMEGA)/D(N) = Z*NY-Y*NZ SUR LE CONTOUR DE LA SECTION -# --- ET SOMME_SECTION(OMEGA.DS) = 0 ( CETTE CONDITION -# --- VENANT DE L EQUATION D EQUILIBRE SELON L AXE DE LA POUTRE -# --- N = 0, N ETANT L EFFORT NORMAL) : -# ------------------------------- - - __tempe4=THER_LINEAIRE(MODELE=__nomot2, - CHAM_MATER=__chmat2, - EXCIT=(_F(CHARGE=__chart5,), - _F(CHARGE=__chart6,),), - SOLVEUR=_F(METHODE='LDLT', - RENUM='SANS', - STOP_SINGULIER='NON',), ) - -# --- CALCUL DE L INERTIE DE GAUCHISSEMENT : -# ------------------------------------- - - nomres=POST_ELEM(reuse=nomres, - MODELE=__nomot2, - CHAM_MATER=__chmat2, - CARA_POUTRE=_F(CARA_GEOM=nomres, - LAPL_PHI=__tempe4, - TOUT='OUI', - OPTION='CARA_GAUCHI'), ) - -# -# ================================================================== -# --- = CALCUL DE LA CONSTANTE DE TORSION SUR CHAQUE GROUPE = -# --- = ET DU CENTRE DE TORSION/CISAILLEMENT = -# --- = DES COEFFICIENTS DE CISAILLEMENT = -# ================================================================== -# - - - if GROUP_MA_BORD and GROUP_MA: - - if type(GROUP_MA_BORD)==types.StringType : - l_group_ma_bord=[GROUP_MA_BORD,] - else: - l_group_ma_bord= GROUP_MA_BORD - if type(GROUP_MA)==types.StringType : - l_group_ma=[GROUP_MA,] - else: - l_group_ma= GROUP_MA - - if NOEUD: - if type(NOEUD)==types.StringType : - l_noeud=[NOEUD,] - else: - l_noeud= NOEUD - - if len(l_group_ma)!=len(l_group_ma_bord): - ier=ier+1 - self.cr.fatal("GROUP_MA et GROUP_MA_BORD incoherents") - return ier - if NOEUD and (len(l_group_ma)!=len(l_noeud)): - ier=ier+1 - self.cr.fatal("GROUP_MA et NOEUD incoherents") - return ier - - for i in range(0,len(l_group_ma_bord)): - -# --- TRANSFORMATION DES GROUP_MA EN GROUP_NO SUR-LESQUELS -# --- ON POURRA APPLIQUER DES CONDITIONS DE TEMPERATURE IMPOSEE : -# --------------------------------------------------------- - - __nomlma=DEFI_GROUP(reuse=__nomlma, - MAILLAGE=__nomlma, - CREA_GROUP_NO=_F(GROUP_MA=l_group_ma_bord[i],) ) - - -# --- CREATION D UN MAILLAGE IDENTIQUE AU PREMIER A CECI PRES -# --- QUE LES COORDONNEES SONT EXPRIMEES DANS LE REPERE PRINCIPAL -# --- D INERTIE DONT L ORIGINE EST LE CENTRE DE GRAVITE DE LA SECTION : -# --------------------------------------------------------------- - - __nomapi=CREA_MAILLAGE(MAILLAGE=__nomlma, - REPERE=_F(TABLE=nomres, - NOM_ORIG='CDG', - GROUP_MA=l_group_ma[i], ), ) - -# --- AFFECTATION DU PHENOMENE 'THERMIQUE' AU MODELE EN VUE DE -# --- LA CONSTRUCTION D UN OPERATEUR LAPLACIEN SUR CE MODELE : -# ------------------------------------------------------ - - __nomoth=AFFE_MODELE(MAILLAGE=__nomapi, - AFFE=_F(GROUP_MA=l_group_ma[i], - PHENOMENE='THERMIQUE', - MODELISATION='PLAN', ) ) - -# --- POUR LA CONSTRUCTION DU LAPLACIEN, ON DEFINIT UN -# --- PSEUDO-MATERIAU DONT LES CARACTERISTIQUES THERMIQUES SONT : -# --- LAMBDA = 1, RHO*CP = 0 : -# ---------------------- - - __nomath=DEFI_MATERIAU(THER=_F(LAMBDA=1.0, - RHO_CP=0.0, ), ) - -# --- DEFINITION D UN CHAM_MATER A PARTIR DU MATERIAU PRECEDENT : -# --------------------------------------------------------- - - __chmath=AFFE_MATERIAU(MAILLAGE=__nomapi, - AFFE=_F(TOUT='OUI', - MATER=__nomath ), ) - -# -# ------------------------------------------------------------ -# --- - CALCUL DE LA CONSTANTE DE TORSION PAR RESOLUTION - -# --- - D UN LAPLACIEN AVEC UN TERME SOURCE EGAL A -2 - -# --- - L INCONNUE ETANT NULLE SUR LE CONTOUR DE LA SECTION : - -# --- - LAPLACIEN(PHI) = -2 DANS LA SECTION - -# --- - PHI = 0 SUR LE CONTOUR : - -# ------------------------------------------------------------ -# -# --- ON IMPOSE LA VALEUR 0 A L INCONNUE SCALAIRE SUR LE CONTOUR -# --- DE LA SECTION -# --- ET ON A UN TERME SOURCE EGAL A -2 DANS TOUTE LA SECTION : -# ------------------------------------------------------- - - __chart1=AFFE_CHAR_THER(MODELE=__nomoth, - TEMP_IMPO=_F(GROUP_NO=l_group_ma_bord[i], - TEMP=0.0 ), - SOURCE=_F(TOUT='OUI', - SOUR=2.0 ) ) - -# --- RESOLUTION DE LAPLACIEN(PHI) = -2 -# --- AVEC PHI = 0 SUR LE CONTOUR : -# ---------------------------------------- - - __tempe1=THER_LINEAIRE(MODELE=__nomoth, - CHAM_MATER=__chmath, - EXCIT=_F(CHARGE=__chart1, ), - SOLVEUR=_F(STOP_SINGULIER='NON',) ) - -# -# ---------------------------------------------- -# --- - CALCUL DU CENTRE DE TORSION/CISAILLEMENT - -# --- - ET DES COEFFICIENTS DE CISAILLEMENT : - -# ---------------------------------------------- -# -# --- POUR LE CALCUL DES CONSTANTES DE CISAILLEMENT, ON VA DEFINIR -# --- UN PREMIER TERME SOURCE, SECOND MEMBRE DE L EQUATION DE LAPLACE -# --- PAR UNE FONCTION EGALE A Y : -# -------------------------- - - __fnsec1=DEFI_FONCTION(NOM_PARA='X', - VALE=(0.,0.,10.,10.), - PROL_DROITE='LINEAIRE', - PROL_GAUCHE='LINEAIRE', ) - - __fnsec0=DEFI_CONSTANTE(VALE=0.,) - -# --- LE TERME SOURCE CONSTITUANT LE SECOND MEMBRE DE L EQUATION -# --- DE LAPLACE EST PRIS EGAL A Y DANS TOUTE LA SECTION : -# -------------------------------------------------- - - __chart2=AFFE_CHAR_THER_F(MODELE=__nomoth, - TEMP_IMPO=_F(NOEUD=l_noeud[i], - TEMP=__fnsec0), - SOURCE=_F(TOUT='OUI', - SOUR=__fnsec1) ) - -# --- RESOLUTION DE LAPLACIEN(PHI) = -Y -# --- AVEC D(PHI)/D(N) = 0 SUR LE CONTOUR : -# ------------------------------------------------ - - __tempe2=THER_LINEAIRE(MODELE=__nomoth, - CHAM_MATER=__chmath, - EXCIT=_F(CHARGE=__chart2, ), - SOLVEUR=_F(STOP_SINGULIER='NON',) ) - -# --- POUR LE CALCUL DES CONSTANTES DE CISAILLEMENT, ON VA DEFINIR -# --- UN PREMIER TERME SOURCE, SECOND MEMBRE DE L EQUATION DE LAPLACE -# --- PAR UNE FONCTION EGALE A Z : -# -------------------------- - - __fnsec2=DEFI_FONCTION(NOM_PARA='Y', - VALE=(0.,0.,10.,10.), - PROL_DROITE='LINEAIRE', - PROL_GAUCHE='LINEAIRE', ) - -# --- LE TERME SOURCE CONSTITUANT LE SECOND MEMBRE DE L EQUATION -# --- DE LAPLACE EST PRIS EGAL A Z DANS TOUTE LA SECTION : -# -------------------------------------------------- - - __chart3=AFFE_CHAR_THER_F(MODELE=__nomoth, - TEMP_IMPO=_F(NOEUD=l_noeud[i], - TEMP=__fnsec0), - SOURCE=_F(TOUT='OUI', - SOUR=__fnsec2) ) - -# --- RESOLUTION DE LAPLACIEN(PHI) = -Z -# --- AVEC D(PHI)/D(N) = 0 SUR LE CONTOUR : -# ------------------------------------------------ - - __tempe3=THER_LINEAIRE(MODELE=__nomoth, - CHAM_MATER=__chmath, - EXCIT=_F(CHARGE=__chart3, ), - SOLVEUR=_F(STOP_SINGULIER='NON',) ) - -# --- CALCUL DE LA CONSTANTE DE TORSION : -# --------------------------------- - - nomres=POST_ELEM(reuse=nomres, - MODELE=__nomoth, - CHAM_MATER=__chmath, - CARA_POUTRE=_F(CARA_GEOM=nomres, - LAPL_PHI=__tempe1, - GROUP_MA=l_group_ma[i], - OPTION='CARA_TORSION' ), ) - -# --- CALCUL DES COEFFICIENTS DE CISAILLEMENT ET DES COORDONNEES DU -# --- CENTRE DE CISAILLEMENT/TORSION : -# ------------------------------ - - nomres=POST_ELEM(reuse=nomres, - MODELE=__nomoth, - CHAM_MATER=__chmath, - CARA_POUTRE=_F(CARA_GEOM=nomres, - LAPL_PHI_Y=__tempe2, - LAPL_PHI_Z=__tempe3, - GROUP_MA=l_group_ma[i], - LONGUEUR=LONGUEUR, - MATERIAU=MATERIAU, - LIAISON =LIAISON, - OPTION='CARA_CISAILLEMENT' ), ) - - return ier - diff --git a/Aster/Cata/Macro/macro_matr_asse_ops.py b/Aster/Cata/Macro/macro_matr_asse_ops.py index 5466b685..4c7f99f1 100644 --- a/Aster/Cata/Macro/macro_matr_asse_ops.py +++ b/Aster/Cata/Macro/macro_matr_asse_ops.py @@ -1,21 +1,21 @@ -#@ MODIF macro_matr_asse_ops Macro DATE 14/09/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF macro_matr_asse_ops Macro DATE 01/04/2005 AUTEUR VABHHTS J.PELLET # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== # COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG -# THIS PROGRAM 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 2 OF THE LICENSE, OR -# (AT YOUR OPTION) ANY LATER VERSION. -# -# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, -# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. +# THIS PROGRAM 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 2 OF THE LICENSE, OR +# (AT YOUR OPTION) ANY LATER VERSION. +# +# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, +# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. # ====================================================================== @@ -58,6 +58,15 @@ def macro_matr_asse_ops(self,MODELE,CHAM_MATER,CARA_ELEM,MATR_ASSE, ier=ier+1 self.cr.fatal(" Avec methode MULT_FRONT, RENUM doit etre MDA, MD ou RCMK.") return ier + elif methode=='MUMPS': + if SOLVEUR['RENUM']: + renum=SOLVEUR['RENUM'] + else: + renum='SANS' + if renum not in ('SANS',): + ier=ier+1 + self.cr.fatal(" Avec methode MUMPS, RENUM doit etre SANS.") + return ier elif methode=='GCPC': if SOLVEUR['RENUM']: renum=SOLVEUR['RENUM'] @@ -81,7 +90,7 @@ def macro_matr_asse_ops(self,MODELE,CHAM_MATER,CARA_ELEM,MATR_ASSE, lrigel = 0 lmasel = 0 -# decalage eventuel en premiere position dans la liste de l occurence de MATR_ASSE contenant +# decalage eventuel en premiere position dans la liste de l occurence de MATR_ASSE contenant # l option de rigidite try : for m in MATR_ASSE: @@ -103,20 +112,6 @@ def macro_matr_asse_ops(self,MODELE,CHAM_MATER,CARA_ELEM,MATR_ASSE, self.cr.fatal(" UNE DES OPTIONS DOIT ETRE RIGI_MECA OU RIGI_THER OU RIGI_ACOU OU RIGI_MECA_LAGR") return ier - if m['SIEF_ELGA']!=None and option!='RIGI_GEOM': - ier=ier+1 - self.cr.fatal(" SIEF_ELGA N EST ADMIS QU AVEC L OPTION RIGI_GEOM") - return ier - - if m['MODE_FOURIER']!=None and option not in ('RIGI_MECA','RIGI_FLUI_STRU','RIGI_THER'): - ier=ier+1 - self.cr.fatal(" MODE_FOURIER N EST ADMIS QU AVEC UNE DES OPTIONS RIGI_MECA RIGI_FLUI_STRU RIGI_THER") - return ier - - if (m['THETA']!=None or m['PROPAGATION']!=None) and option!='RIGI_MECA_LAGR': - ier=ier+1 - self.cr.fatal(" PROPAGATION ET,OU THETA NE SONT ADMIS QU AVEC L OPTION RIGI_MECA_LAGR") - return ier motscles={'OPTION':option} if option == 'AMOR_MECA': @@ -134,11 +129,19 @@ def macro_matr_asse_ops(self,MODELE,CHAM_MATER,CARA_ELEM,MATR_ASSE, if CHAM_MATER != None: motscles['CHAM_MATER'] =CHAM_MATER if CARA_ELEM != None: motscles['CARA_ELEM'] =CARA_ELEM if INST != None: motscles['INST'] =INST - if m['SIEF_ELGA'] : motscles['SIEF_ELGA'] =m['SIEF_ELGA'] - if m['MODE_FOURIER']: motscles['MODE_FOURIER']=m['MODE_FOURIER'] - if m['THETA'] : motscles['THETA'] =m['THETA'] - if m['PROPAGATION'] : motscles['PROPAGATION'] =m['PROPAGATION'] + try : motscles['SIEF_ELGA'] =m['SIEF_ELGA'] + except IndexError : pass + + try : motscles['MODE_FOURIER'] =m['MODE_FOURIER'] + except IndexError : pass + + try : motscles['THETA'] =m['THETA'] + except IndexError : pass + + try : motscles['PROPAGATION'] =m['PROPAGATION'] + except IndexError : pass + print motscles __a=CALC_MATR_ELEM(MODELE=MODELE,**motscles) if option == 'RIGI_MECA': diff --git a/Aster/Cata/Macro/pre_gmsh_ops.py b/Aster/Cata/Macro/pre_gmsh_ops.py deleted file mode 100644 index 8ff4170e..00000000 --- a/Aster/Cata/Macro/pre_gmsh_ops.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -#@ MODIF pre_gmsh_ops Macro DATE 11/06/2002 AUTEUR DURAND C.DURAND -# CONFIGURATION MANAGEMENT OF EDF VERSION -# ====================================================================== -# COPYRIGHT (C) 1991 - 2002 EDF R&D WWW.CODE-ASTER.ORG -# THIS PROGRAM 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 2 OF THE LICENSE, OR -# (AT YOUR OPTION) ANY LATER VERSION. -# -# THIS PROGRAM 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 THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER, -# 1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE. -# ====================================================================== - -def pre_gmsh_ops(self,UNITE_MAILLAGE,UNITE_GMSH,MODI_QUAD,**args): - """ - Ecriture de la macro PRE_GMSH - """ - import os - from Macro.ajout_quad_gmsh import ajout_quad_gmsh - ier=0 - - PRE_GMSH_LECT =self.get_cmd('PRE_GMSH_LECT') - - # La macro compte pour 1 dans la numerotation des commandes - self.icmd=1 - - if MODI_QUAD=='OUI': - cur_dir=os.getcwd() - unit = str(UNITE_GMSH) - nomFichierGmsh = cur_dir+'/fort.'+unit - nomFichierMail = cur_dir+'/sortie' - -# récupération du fichier .msh complet mis dans la string 'texte' - - fproc=open(nomFichierGmsh,'r') - texte=fproc.read() - fproc.close() - - resu=ajout_quad_gmsh(texte) - if not resu: - ier=ier+1 - self.cr.fatal("Erreur dans la methode python de transformation mailles lineaires-quadratiques") - return ier - - fsort=open(nomFichierMail,'w') - fsort.write(resu) - fsort.close() - os.system('cp '+nomFichierMail+' '+nomFichierGmsh) - - PRE_GMSH_LECT(UNITE_MAILLAGE = UNITE_MAILLAGE, - UNITE_GMSH = UNITE_GMSH ) - - return ier - diff --git a/Aster/Cata/Macro/reca_algo.py b/Aster/Cata/Macro/reca_algo.py index 319d6d67..65e02bd1 100644 --- a/Aster/Cata/Macro/reca_algo.py +++ b/Aster/Cata/Macro/reca_algo.py @@ -1,4 +1,4 @@ -#@ MODIF reca_algo Macro DATE 14/09/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF reca_algo Macro DATE 14/03/2005 AUTEUR DURAND C.DURAND # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -26,7 +26,6 @@ import copy,os import LinearAlgebra from Cata.cata import INFO_EXEC_ASTER from Cata.cata import DETRUIRE -from Macro.recal import EXTRACT from Accas import _F diff --git a/Aster/Cata/Macro/recal.py b/Aster/Cata/Macro/recal.py index cb2d4778..591614c8 100644 --- a/Aster/Cata/Macro/recal.py +++ b/Aster/Cata/Macro/recal.py @@ -1,4 +1,4 @@ -#@ MODIF recal Macro DATE 14/09/2004 AUTEUR MCOURTOI M.COURTOIS +#@ MODIF recal Macro DATE 14/03/2005 AUTEUR DURAND C.DURAND # -*- coding: iso-8859-1 -*- # CONFIGURATION MANAGEMENT OF EDF VERSION # ====================================================================== @@ -29,7 +29,6 @@ import Gnuplot import Cata from Cata.cata import INCLUDE,DETRUIRE from Accas import _F -from Utilitai.extract import EXTRACT import os @@ -151,13 +150,14 @@ def calcul_F(self,UL,para,val,reponses): Fichier_Resu.append(post_bloc) #-------------------------------------------------------------------------------- - #on va ajouter la fonction EXTRACT + #on va ajouter la fonction d'extraction du numarray de la table par la méthode Array #et on stocke les réponses calculées dans la liste Lrep #qui va etre retournée par la fonction calcul_F self.g_context['Lrep'] = [] Fichier_Resu.append('Lrep=[]'+'\n') for i in range(len(reponses)): - Fichier_Resu.append('F = EXTRACT('+str(reponses[i][0])+','+"'"+str(reponses[i][1])+"'"+','+"'"+str(reponses[i][2])+"'"+')'+'\n') + Fichier_Resu.append('t'+str(reponses[i][0])+'='+str(reponses[i][0])+'.EXTR_TABLE()'+'\n') + Fichier_Resu.append('F = '+'t'+str(reponses[i][0])+'.Array('+"'"+str(reponses[i][1])+"'"+','+"'"+str(reponses[i][2])+"'"+')'+'\n') Fichier_Resu.append('Lrep.append(F)'+'\n') #ouverture du fichier fort.3 et mise a jour de celui ci diff --git a/Pmw/Alpha_99_9_example/__init__.py b/Pmw/Alpha_99_9_example/__init__.py new file mode 100644 index 00000000..83d04e76 --- /dev/null +++ b/Pmw/Alpha_99_9_example/__init__.py @@ -0,0 +1 @@ +# File to allow this directory to be treated as a python package. diff --git a/Pmw/Alpha_99_9_example/lib/Pmw.def b/Pmw/Alpha_99_9_example/lib/Pmw.def new file mode 100644 index 00000000..358a2b46 --- /dev/null +++ b/Pmw/Alpha_99_9_example/lib/Pmw.def @@ -0,0 +1,9 @@ +# Widgets whose name is the same as its module. +_widgets = ('AlphaExample',) + +# Widgets whose name is not the same as its module. +_extraWidgets = {} + +_functions = {} + +_modules = () diff --git a/Pmw/Alpha_99_9_example/lib/PmwAlphaExample.py b/Pmw/Alpha_99_9_example/lib/PmwAlphaExample.py new file mode 100644 index 00000000..5e4f88c1 --- /dev/null +++ b/Pmw/Alpha_99_9_example/lib/PmwAlphaExample.py @@ -0,0 +1,24 @@ +import string +import Pmw + +_default_text = "AlphaExample example alpha Pmw megawidget.\nPmw version: " + \ + Pmw.version() + '\nPmw Alpha versions: ' + \ + string.join(Pmw.version(alpha = 1), ' ') + +class AlphaExample(Pmw.MessageDialog): + # Dummy widget for illustrating use of Pmw alpha version directory + + def __init__(self, parent = None, **kw): + + # Define the megawidget options. + INITOPT = Pmw.INITOPT + optiondefs = ( + ('message_text', _default_text, None), + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MessageDialog.__init__(self, parent) + + # Check keywords and initialise options. + self.initialiseoptions(AlphaExample) diff --git a/Pmw/Alpha_99_9_example/lib/__init__.py b/Pmw/Alpha_99_9_example/lib/__init__.py new file mode 100644 index 00000000..83d04e76 --- /dev/null +++ b/Pmw/Alpha_99_9_example/lib/__init__.py @@ -0,0 +1 @@ +# File to allow this directory to be treated as a python package. diff --git a/Pmw/Pmw_1_2/__init__.py b/Pmw/Pmw_1_2/__init__.py new file mode 100644 index 00000000..83d04e76 --- /dev/null +++ b/Pmw/Pmw_1_2/__init__.py @@ -0,0 +1 @@ +# File to allow this directory to be treated as a python package. diff --git a/Pmw/Pmw_1_2/bin/bundlepmw.py b/Pmw/Pmw_1_2/bin/bundlepmw.py new file mode 100755 index 00000000..fdb7dc00 --- /dev/null +++ b/Pmw/Pmw_1_2/bin/bundlepmw.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +# Helper script when freezing Pmw applications. It concatenates all +# Pmw megawidget files into a single file, 'Pmw.py', in the current +# directory. The script must be called with one argument, being the +# path to the 'lib' directory of the required version of Pmw. +# To freeze a Pmw application, you will also need to copy the +# following files to the application directory before freezing: +# +# PmwBlt.py PmwColor.py + +import os +import regsub +import string +import sys + +# The order of these files is significant. Files which reference +# other files must appear later. Files may be deleted if they are not +# used. +files = [ + 'Dialog', 'TimeFuncs', 'Balloon', 'ButtonBox', 'EntryField', + 'Group', 'LabeledWidget', 'MainMenuBar', 'MenuBar', 'MessageBar', + 'MessageDialog', 'NoteBook', 'OptionMenu', 'PanedWidget', 'PromptDialog', + 'RadioSelect', 'ScrolledCanvas', 'ScrolledField', 'ScrolledFrame', + 'ScrolledListBox', 'ScrolledText', 'HistoryText', 'SelectionDialog', + 'TextDialog', 'TimeCounter', 'AboutDialog', 'ComboBox', 'ComboBoxDialog', + 'Counter', 'CounterDialog', +] + +# Set this to 0 if you do not use any of the Pmw.Color functions: +needColor = 1 + +# Set this to 0 if you do not use any of the Pmw.Blt functions: +needBlt = 1 + +def expandLinks(path): + if not os.path.isabs(path): + path = os.path.join(os.getcwd(), path) + while 1: + if not os.path.islink(path): + break + dir = os.path.dirname(path) + path = os.path.join(dir, os.readlink(path)) + + return path + +def mungeFile(file): + # Read the file and modify it so that it can be bundled with the + # other Pmw files. + file = 'Pmw' + file + '.py' + text = open(os.path.join(srcdir, file)).read() + text = regsub.gsub('import Pmw\>', '', text) + text = regsub.gsub('INITOPT = Pmw.INITOPT', '', text) + text = regsub.gsub('\ +# +# Copyright 2001 MontaVista Software Inc. +# +# This program 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 2 of the License, or (at your +# option) any later version. +# +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +# NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 675 Mass Ave, Cambridge, MA 02139, USA. +# + + +import os +import Tkinter +import Pmw + + +class DirBrowserDialog(Pmw.MegaToplevel): + def __init__(self, parent = None, **kw): + cwd = os.getcwd() + # Define the megawidget options. + INITOPT = Pmw.INITOPT + optiondefs = ( + ('path', cwd, None), + ('hidedotfiles', 1, INITOPT), + ('label', None, INITOPT), + #('labelmargin', 0, INITOPT), + #('labelpos', None, INITOPT), + ('borderx', 20, INITOPT), + ('bordery', 20, INITOPT), + ) + + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaToplevel.__init__(self, parent) + + interior = self.interior() + + self.childframe = self.createcomponent('childframe', (), None, + Tkinter.Frame, + (interior,), + borderwidth = 1, + relief = 'raised', + ) + self.childframe.pack(expand = 1, + fill = 'both', + ) + + self.labelframe = self.createcomponent('labelframe', (), None, + Tkinter.Frame, + (self.childframe,), + borderwidth = 2, + relief = 'groove', + ) + self.labelframe.pack(padx = 10, pady = 10, expand = 1, fill = 'both') + + if self['label']: + self.label = self.createcomponent('label', (), None, + Tkinter.Label, + (self.childframe,), + text = self['label'], + ) + self.label.place(x = (10 + self['borderx']), y = 10, anchor = 'w') + + + self.workframe = self.createcomponent('workframe', (), None, + Tkinter.Frame, + (self.labelframe,), + #borderwidth = 2, + #relief = 'groove', + ) + self.workframe.pack(padx = self['borderx'], + pady = self['bordery'], + expand = 1, + fill = 'both', + ) + + self.buttonframe = self.createcomponent('buttonframe', (), None, + Tkinter.Frame, + (interior,), + borderwidth = 1, + relief = 'raised', + ) + self.buttonframe.pack(expand = 0, + fill = 'x', + ) + + self.optbox = self.createcomponent('optbox', (), None, + Pmw.OptionMenu, + (self.workframe,), + command = self.setpath, + ) + self.optbox.bind('', self._setMinimumSize) + + self.listbox = self.createcomponent('listbox', (), None, + Pmw.ScrolledListBox, + (self.workframe,), + dblclickcommand = self._select, + ) + + path = self['path'] + self.entry = self.createcomponent('entryfield', (), None, + Pmw.EntryField, + (self.workframe,), + value = path, + command = self.enteredpath, + labelpos = 'nw', + label_text = 'Current Path:', + ) + + #self.createlabel(self.workframe, childCols = 1, childRows = 3) + + self.buttonbox = self.createcomponent('buttonbox', (), None, + Pmw.ButtonBox, + (self.buttonframe,), + ) + self.buttonbox.add('OK', text = 'OK', + command = self.okbutton) + self.buttonbox.add('Cancel', text = 'Cancel', + command = self.cancelbutton) + self.buttonbox.add('New Directory', text = 'New Directory', + command = self.newdirbutton) + + self.buttonbox.alignbuttons() + self.buttonbox.pack(expand = 1, fill = 'x') + + self.optbox.grid(row = 2, column = 2, sticky = 'ew') + self.listbox.grid(row = 3, column = 2, sticky = 'news') + self.entry.grid(row = 5, column = 2, sticky = 'ew') + self.workframe.grid_rowconfigure(3, weight = 1) + self.workframe.grid_rowconfigure(4, minsize = 20) + self.workframe.grid_columnconfigure(2, weight = 1) + + + self.setpath(self['path']) + + # Check keywords and initialise options. + self.initialiseoptions() + + def setpath(self, path): + path = os.path.abspath(os.path.expanduser(path)) + + if os.path.isfile(path): + path = os.path.dirname(path) + + dirlist = [] + hidedotfiles = self['hidedotfiles'] + try: + posix = (os.name == 'posix') + for entry in os.listdir(path): + entryPath = path + '/' + entry + if hidedotfiles and entry[0] == '.': + # skip dot files if desired + continue + if not os.path.isdir(entryPath): + # skip files + continue + if not os.access(entryPath, os.R_OK | os.X_OK): + # skip directories we can't enter any way + continue + dirlist.append(entry) + + except: + self.entry.setentry(self['path']) + return + + self.entry.setentry(path) + + self['path'] = path + + dirlist.sort() + if path != '/': + dirlist.insert(0, '..') + + self.listbox.setlist(dirlist) + pathlist = [] + while path != '/': + pathlist.append(path) + path = os.path.dirname(path) + pathlist.append('/') + self.optbox.setitems(pathlist, 0) + + def _setMinimumSize(self, event): + # If the optionmenu changes width, make sure it does not + # shrink later. + owidth = self.optbox.winfo_width() + self.workframe.grid_columnconfigure(2, minsize = owidth) + + def _select(self): + sel = self.listbox.getcurselection() + if self['path'] == '/': + self['path'] = '' + if len(sel) > 0: + if sel[0] == '..': + self.setpath(os.path.dirname(self['path'])) + else: + self.setpath(self['path'] + '/' + sel[0]) + + + def getcurpath(self): + return self['path'] + + def enteredpath(self): + self.setpath(self.entry.get()) + + def okbutton(self): + self.deactivate(self['path']) + + def cancelbutton(self): + self.deactivate(None) + + def newdirbutton(self): + CreateDirectoryPopup(self.interior(), self['path']) + self.setpath(self['path']) + + + +class CreateDirectoryPopup: + def __init__(self, parent, path): + self.path = path + self.parent = parent + self.newdirpopup = Pmw.PromptDialog(parent, + buttons = ('OK', 'Cancel'), + defaultbutton = 'OK', + title = 'New Directory', + entryfield_labelpos = 'nw', + label_text = 'Enter new directory name for:\n%s'%self.path, + command = self._buttonpress + ) + + self.newdirpopup.activate() + + def _buttonpress(self, button): + if button == 'OK': + newdirname = self.newdirpopup.get() + dirlist = os.listdir(self.path) + if newdirname in dirlist: + ErrorPopup(self.parent, + 'Error: "%s", already exists as a file or directory.'%newdirname) + else: + try: + os.mkdir(self.path + '/' + newdirname) + except: + ErrorPopup(self.parent, + 'Error: Could not create directory: "%s"'%newdirname) + else: + self.newdirpopup.deactivate() + else: + self.newdirpopup.deactivate() + + +def ErrorPopup(parent, message): + error = Pmw.MessageDialog(parent, title = 'Error', + message_text = message, + defaultbutton = 0, + ) + error.activate() + +if __name__ == '__main__': + + rootWin = Tkinter.Tk() + + Pmw.initialise() + + rootWin.title('Directory Browser Dialog Demo') + + def buildBrowser(): + # Create the hierarchical directory browser widget + dirBrowserDialog = DirBrowserDialog(rootWin, + #labelpos = 'nw', + label = 'Select a directory', + title = 'Directory Selector', + #path = '~', + #hidedotfiles = 0, + ) + dir = dirBrowserDialog.activate() + print 'Selected Directory:', dir + + dirButton = Tkinter.Button(rootWin, text="Browser", command=buildBrowser) + dirButton.pack(side = 'left', padx = 10, pady = 10) + + exitButton = Tkinter.Button(rootWin, text="Quit", command=rootWin.quit) + exitButton.pack(side = 'left', padx = 10, pady = 10) + + rootWin.mainloop() diff --git a/Pmw/Pmw_1_2/contrib/MCListbox.py b/Pmw/Pmw_1_2/contrib/MCListbox.py new file mode 100644 index 00000000..166b8a04 --- /dev/null +++ b/Pmw/Pmw_1_2/contrib/MCListbox.py @@ -0,0 +1,706 @@ +# +# FILE: MCListbox.py +# +# DESCRIPTION: +# This file provides a generic Multi-Column Listbox widget. It is derived +# from a heavily hacked version of Pmw.ScrolledFrame +# +# This program 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 2 of the License, or (at your +# option) any later version. +# +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +# NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import string +import Tkinter +import Pmw + +class MultiColumnListbox(Pmw.MegaWidget): + def __init__(self, parent = None, **kw): + colors = Pmw.Color.getdefaultpalette(parent) + + # Define the megawidget options. + INITOPT = Pmw.INITOPT + optiondefs = ( + #('borderframe', 1, INITOPT), + ('horizflex', 'fixed', self._horizflex), + ('horizfraction', 0.05, INITOPT), + ('hscrollmode', 'dynamic', self._hscrollMode), + ('labelmargin', 0, INITOPT), + ('labelpos', None, INITOPT), + ('scrollmargin', 2, INITOPT), + ('usehullsize', 0, INITOPT), + ('vertflex', 'fixed', self._vertflex), + ('vertfraction', 0.05, INITOPT), + ('vscrollmode', 'dynamic', self._vscrollMode), + ('labellist', None, INITOPT), + ('selectbackground', colors['selectBackground'], INITOPT), + ('selectforeground', colors['selectForeground'], INITOPT), + ('background', colors['background'], INITOPT), + ('foreground', colors['foreground'], INITOPT), + ('command', None, None), + ('dblclickcommand', None, None), + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaWidget.__init__(self, parent) + + self._numcolumns = len(self['labellist']) + self._columnlabels = self['labellist'] + self._lineid = 0 + self._numrows = 0 + self._lineitemframes = [] + self._lineitems = [] + self._lineitemdata = {} + self._labelframe = {} + self._cursel = [] + + # Create the components. + self.origInterior = Pmw.MegaWidget.interior(self) + + if self['usehullsize']: + self.origInterior.grid_propagate(0) + + # Create a frame widget to act as the border of the clipper. + self._borderframe = self.createcomponent('borderframe', + (), None, + Tkinter.Frame, + (self.origInterior,), + relief = 'sunken', + borderwidth = 2, + ) + self._borderframe.grid(row = 2, column = 2, + rowspan = 2, sticky = 'news') + + # Create the clipping windows. + self._hclipper = self.createcomponent('hclipper', + (), None, + Tkinter.Frame, + (self._borderframe,), + width = 400, + height = 300, + ) + self._hclipper.pack(fill = 'both', expand = 1) + + self._hsframe = self.createcomponent('hsframe', (), None, + Tkinter.Frame, + (self._hclipper,), + ) + + + self._vclipper = self.createcomponent('vclipper', + (), None, + Tkinter.Frame, + (self._hsframe,), + #width = 400, + #height = 300, + highlightthickness = 0, + borderwidth = 0, + ) + + self._vclipper.grid(row = 1, column = 0, + columnspan = self._numcolumns, + sticky = 'news')#, expand = 1) + self._hsframe.grid_rowconfigure(1, weight = 1)#, minsize = 300) + + + gridcolumn = 0 + for labeltext in self._columnlabels: + lframe = self.createcomponent(labeltext+'frame', (), None, + Tkinter.Frame, + (self._hsframe,), + borderwidth = 1, + relief = 'raised', + ) + label = self.createcomponent(labeltext, (), None, + Tkinter.Label, + (lframe,), + text = labeltext, + ) + label.pack(expand = 0, fill = 'y', side = 'left') + lframe.grid(row = 0, column = gridcolumn, sticky = 'ews') + self._labelframe[labeltext] = lframe + #lframe.update() + #print lframe.winfo_reqwidth() + self._hsframe.grid_columnconfigure(gridcolumn, weight = 1) + gridcolumn = gridcolumn + 1 + + lframe.update() + self._labelheight = lframe.winfo_reqheight() + self.origInterior.grid_rowconfigure(2, minsize = self._labelheight + 2) + + self.origInterior.grid_rowconfigure(3, weight = 1, minsize = 0) + self.origInterior.grid_columnconfigure(2, weight = 1, minsize = 0) + + # Create the horizontal scrollbar + self._horizScrollbar = self.createcomponent('horizscrollbar', + (), 'Scrollbar', + Tkinter.Scrollbar, + (self.origInterior,), + orient='horizontal', + command=self._xview + ) + + # Create the vertical scrollbar + self._vertScrollbar = self.createcomponent('vertscrollbar', + (), 'Scrollbar', + Tkinter.Scrollbar, + (self.origInterior,), + #(self._hclipper,), + orient='vertical', + command=self._yview + ) + + self.createlabel(self.origInterior, childCols = 3, childRows = 4) + + # Initialise instance variables. + self._horizScrollbarOn = 0 + self._vertScrollbarOn = 0 + self.scrollTimer = None + self._scrollRecurse = 0 + self._horizScrollbarNeeded = 0 + self._vertScrollbarNeeded = 0 + self.startX = 0 + self.startY = 0 + self._flexoptions = ('fixed', 'expand', 'shrink', 'elastic') + + # Create a frame in the clipper to contain the widgets to be + # scrolled. + self._vsframe = self.createcomponent('vsframe', + (), None, + Tkinter.Frame, + (self._vclipper,), + #height = 300, + #borderwidth = 4, + #relief = 'groove', + ) + + # Whenever the clipping window or scrolled frame change size, + # update the scrollbars. + self._hsframe.bind('', self._reposition) + self._vsframe.bind('', self._reposition) + self._hclipper.bind('', self._reposition) + self._vclipper.bind('', self._reposition) + + #elf._vsframe.bind('', self._vsframeselect) + + # Check keywords and initialise options. + self.initialiseoptions() + + def destroy(self): + if self.scrollTimer is not None: + self.after_cancel(self.scrollTimer) + self.scrollTimer = None + Pmw.MegaWidget.destroy(self) + + # ====================================================================== + + # Public methods. + + def interior(self): + return self._vsframe + + # Set timer to call real reposition method, so that it is not + # called multiple times when many things are reconfigured at the + # same time. + def reposition(self): + if self.scrollTimer is None: + self.scrollTimer = self.after_idle(self._scrollBothNow) + + + + def insertrow(self, index, rowdata): + #if len(rowdata) != self._numcolumns: + # raise ValueError, 'Number of items in rowdata does not match number of columns.' + if index > self._numrows: + index = self._numrows + + rowframes = {} + for columnlabel in self._columnlabels: + celldata = rowdata.get(columnlabel) + cellframe = self.createcomponent(('cellframeid.%d.%s'%(self._lineid, + columnlabel)), + (), ('Cellframerowid.%d'%self._lineid), + Tkinter.Frame, + (self._vsframe,), + background = self['background'], + #borderwidth = 1, + #relief = 'flat' + ) + + cellframe.bind('', self._cellframedblclick) + cellframe.bind('', self._cellframeselect) + + if celldata: + cell = self.createcomponent(('cellid.%d.%s'%(self._lineid, + columnlabel)), + (), ('Cellrowid.%d'%self._lineid), + Tkinter.Label, + (cellframe,), + background = self['background'], + foreground = self['foreground'], + text = celldata, + ) + + cell.bind('', self._celldblclick) + cell.bind('', self._cellselect) + + cell.pack(expand = 0, fill = 'y', side = 'left', padx = 1, pady = 1) + rowframes[columnlabel] = cellframe + + self._lineitemdata[self._lineid] = rowdata + self._lineitems.insert(index, self._lineid) + self._lineitemframes.insert(index, rowframes) + self._numrows = self._numrows + 1 + self._lineid = self._lineid + 1 + + self._placedata(index) + + def _placedata(self, index = 0): + gridy = index + for rowframes in self._lineitemframes[index:]: + gridx = 0 + for columnlabel in self._columnlabels: + rowframes[columnlabel].grid(row = gridy, + column = gridx, + sticky = 'news') + gridx = gridx + 1 + gridy = gridy + 1 + + + + def addrow(self, rowdata): + self.insertrow(self._numrows, rowdata) + + def delrow(self, index): + rowframes = self._lineitemframes.pop(index) + for columnlabel in self._columnlabels: + rowframes[columnlabel].destroy() + self._placedata(index) + self._numrows = self._numrows - 1 + del self._lineitems[index] + if index in self._cursel: + self._cursel.remove(index) + + + def curselection(self): + # Return a tuple of just one element as this will probably be the + # interface used in a future implementation when multiple rows can + # be selected at once. + return tuple(self._cursel) + + def getcurselection(self): + # Return a tuple of just one row as this will probably be the + # interface used in a future implementation when multiple rows can + # be selected at once. + sellist = [] + for sel in self._cursel: + sellist.append(self._lineitemdata[self._lineitems[sel]]) + return tuple(sellist) + + # ====================================================================== + + # Configuration methods. + + def _hscrollMode(self): + # The horizontal scroll mode has been configured. + + mode = self['hscrollmode'] + + + if mode == 'static': + if not self._horizScrollbarOn: + self._toggleHorizScrollbar() + elif mode == 'dynamic': + if self._horizScrollbarNeeded != self._horizScrollbarOn: + self._toggleHorizScrollbar() + elif mode == 'none': + if self._horizScrollbarOn: + self._toggleHorizScrollbar() + else: + message = 'bad hscrollmode option "%s": should be static, dynamic, or none' % mode + raise ValueError, message + + def _vscrollMode(self): + # The vertical scroll mode has been configured. + + mode = self['vscrollmode'] + + if mode == 'static': + if not self._vertScrollbarOn: + self._toggleVertScrollbar() + elif mode == 'dynamic': + if self._vertScrollbarNeeded != self._vertScrollbarOn: + self._toggleVertScrollbar() + elif mode == 'none': + if self._vertScrollbarOn: + self._toggleVertScrollbar() + else: + message = 'bad vscrollmode option "%s": should be static, dynamic, or none' % mode + raise ValueError, message + + def _horizflex(self): + # The horizontal flex mode has been configured. + + flex = self['horizflex'] + + if flex not in self._flexoptions: + message = 'bad horizflex option "%s": should be one of %s' % \ + mode, str(self._flexoptions) + raise ValueError, message + + self.reposition() + + def _vertflex(self): + # The vertical flex mode has been configured. + + flex = self['vertflex'] + + if flex not in self._flexoptions: + message = 'bad vertflex option "%s": should be one of %s' % \ + mode, str(self._flexoptions) + raise ValueError, message + + self.reposition() + + + + # ====================================================================== + + # Private methods. + + def _reposition(self, event): + gridx = 0 + for col in self._columnlabels: + maxwidth = self._labelframe[col].winfo_reqwidth() + for row in self._lineitemframes: + cellwidth = row[col].winfo_reqwidth() + if cellwidth > maxwidth: + maxwidth = cellwidth + self._hsframe.grid_columnconfigure(gridx, minsize = maxwidth) + gridwidth = self._hsframe.grid_bbox(column = gridx, row = 0)[2] + if self['horizflex'] in ('expand', 'elastic') and gridwidth > maxwidth: + maxwidth = gridwidth + self._vsframe.grid_columnconfigure(gridx, minsize = maxwidth) + gridx = gridx + 1 + + + + self._vclipper.configure(height = self._hclipper.winfo_height() - self._labelheight) + + self.reposition() + + # Called when the user clicks in the horizontal scrollbar. + # Calculates new position of frame then calls reposition() to + # update the frame and the scrollbar. + def _xview(self, mode, value, units = None): + + if mode == 'moveto': + frameWidth = self._hsframe.winfo_reqwidth() + self.startX = string.atof(value) * float(frameWidth) + else: + clipperWidth = self._hclipper.winfo_width() + if units == 'units': + jump = int(clipperWidth * self['horizfraction']) + else: + jump = clipperWidth + + if value == '1': + self.startX = self.startX + jump + else: + self.startX = self.startX - jump + + self.reposition() + + # Called when the user clicks in the vertical scrollbar. + # Calculates new position of frame then calls reposition() to + # update the frame and the scrollbar. + def _yview(self, mode, value, units = None): + + if mode == 'moveto': + frameHeight = self._vsframe.winfo_reqheight() + self.startY = string.atof(value) * float(frameHeight) + else: + clipperHeight = self._vclipper.winfo_height() + if units == 'units': + jump = int(clipperHeight * self['vertfraction']) + else: + jump = clipperHeight + + if value == '1': + self.startY = self.startY + jump + else: + self.startY = self.startY - jump + + self.reposition() + + def _getxview(self): + + # Horizontal dimension. + clipperWidth = self._hclipper.winfo_width() + frameWidth = self._hsframe.winfo_reqwidth() + if frameWidth <= clipperWidth: + # The scrolled frame is smaller than the clipping window. + + self.startX = 0 + endScrollX = 1.0 + + if self['horizflex'] in ('expand', 'elastic'): + relwidth = 1 + else: + relwidth = '' + else: + # The scrolled frame is larger than the clipping window. + + if self['horizflex'] in ('shrink', 'elastic'): + self.startX = 0 + endScrollX = 1.0 + relwidth = 1 + else: + if self.startX + clipperWidth > frameWidth: + self.startX = frameWidth - clipperWidth + endScrollX = 1.0 + else: + if self.startX < 0: + self.startX = 0 + endScrollX = (self.startX + clipperWidth) / float(frameWidth) + relwidth = '' + + # Position frame relative to clipper. + self._hsframe.place(x = -self.startX, relwidth = relwidth) + return (self.startX / float(frameWidth), endScrollX) + + def _getyview(self): + + # Vertical dimension. + clipperHeight = self._vclipper.winfo_height() + frameHeight = self._vsframe.winfo_reqheight() + if frameHeight <= clipperHeight: + # The scrolled frame is smaller than the clipping window. + + self.startY = 0 + endScrollY = 1.0 + + if self['vertflex'] in ('expand', 'elastic'): + relheight = 1 + else: + relheight = '' + else: + # The scrolled frame is larger than the clipping window. + + if self['vertflex'] in ('shrink', 'elastic'): + self.startY = 0 + endScrollY = 1.0 + relheight = 1 + else: + if self.startY + clipperHeight > frameHeight: + self.startY = frameHeight - clipperHeight + endScrollY = 1.0 + else: + if self.startY < 0: + self.startY = 0 + endScrollY = (self.startY + clipperHeight) / float(frameHeight) + relheight = '' + + # Position frame relative to clipper. + self._vsframe.place(y = -self.startY, relheight = relheight) + return (self.startY / float(frameHeight), endScrollY) + + # According to the relative geometries of the frame and the + # clipper, reposition the frame within the clipper and reset the + # scrollbars. + def _scrollBothNow(self): + self.scrollTimer = None + + # Call update_idletasks to make sure that the containing frame + # has been resized before we attempt to set the scrollbars. + # Otherwise the scrollbars may be mapped/unmapped continuously. + self._scrollRecurse = self._scrollRecurse + 1 + self.update_idletasks() + self._scrollRecurse = self._scrollRecurse - 1 + if self._scrollRecurse != 0: + return + + xview = self._getxview() + yview = self._getyview() + self._horizScrollbar.set(xview[0], xview[1]) + self._vertScrollbar.set(yview[0], yview[1]) + + self._horizScrollbarNeeded = (xview != (0.0, 1.0)) + self._vertScrollbarNeeded = (yview != (0.0, 1.0)) + + # If both horizontal and vertical scrollmodes are dynamic and + # currently only one scrollbar is mapped and both should be + # toggled, then unmap the mapped scrollbar. This prevents a + # continuous mapping and unmapping of the scrollbars. + if (self['hscrollmode'] == self['vscrollmode'] == 'dynamic' and + self._horizScrollbarNeeded != self._horizScrollbarOn and + self._vertScrollbarNeeded != self._vertScrollbarOn and + self._vertScrollbarOn != self._horizScrollbarOn): + if self._horizScrollbarOn: + self._toggleHorizScrollbar() + else: + self._toggleVertScrollbar() + return + + if self['hscrollmode'] == 'dynamic': + if self._horizScrollbarNeeded != self._horizScrollbarOn: + self._toggleHorizScrollbar() + + if self['vscrollmode'] == 'dynamic': + if self._vertScrollbarNeeded != self._vertScrollbarOn: + self._toggleVertScrollbar() + + def _toggleHorizScrollbar(self): + + self._horizScrollbarOn = not self._horizScrollbarOn + + interior = self.origInterior + if self._horizScrollbarOn: + self._horizScrollbar.grid(row = 5, column = 2, sticky = 'news') + interior.grid_rowconfigure(4, minsize = self['scrollmargin']) + else: + self._horizScrollbar.grid_forget() + interior.grid_rowconfigure(4, minsize = 0) + + def _toggleVertScrollbar(self): + + self._vertScrollbarOn = not self._vertScrollbarOn + + interior = self.origInterior + if self._vertScrollbarOn: + self._vertScrollbar.grid(row = 3, column = 4, sticky = 'news') + interior.grid_columnconfigure(3, minsize = self['scrollmargin']) + else: + self._vertScrollbar.grid_forget() + interior.grid_columnconfigure(3, minsize = 0) + + # ====================================================================== + + # Selection methods. + + #def _vsframeselect(self, event): + # print 'vsframe event x: %d y: %d'%(event.x, event.y) + # col, row = self._vsframe.grid_location(event.x, event.y) + # self._select(col, row) + + def _cellframeselect(self, event): + #print 'cellframe event x: %d y: %d'%(event.x, event.y) + x = event.widget.winfo_x() + y = event.widget.winfo_y() + #col, row = self._vsframe.grid_location(x + event.x, y + event.y) + self._select(x + event.x, y + event.y)#(col, row) + + def _cellselect(self, event): + #print 'cell event x: %d y: %d'%(event.x, event.y) + lx = event.widget.winfo_x() + ly = event.widget.winfo_y() + parent = event.widget.pack_info()['in'] + fx = parent.winfo_x() + fy = parent.winfo_y() + #col, row = self._vsframe.grid_location(fx + lx + event.x, fy + ly + event.y) + self._select(fx + lx + event.x, fy + ly + event.y)#(col, row) + + def _select(self, x, y): + col, row = self._vsframe.grid_location(x, y) + #print 'Clicked on col: %d row: %d'%(col,row) + cfg = {} + lineid = self._lineitems[row] + cfg['Cellrowid.%d_foreground'%lineid] = self['selectforeground'] + cfg['Cellrowid.%d_background'%lineid] = self['selectbackground'] + cfg['Cellframerowid.%d_background'%lineid] = self['selectbackground'] + #cfg['Cellframerowid%d_relief'%row] = 'raised' + + if self._cursel != []: + cursel = self._cursel[0] + lineid = self._lineitems[cursel] + if cursel != None and cursel != row: + cfg['Cellrowid.%d_foreground'%lineid] = self['foreground'] + cfg['Cellrowid.%d_background'%lineid] = self['background'] + cfg['Cellframerowid.%d_background'%lineid] = self['background'] + #cfg['Cellframerowid%d_relief'%cursel] = 'flat' + + apply(self.configure, (), cfg) + self._cursel = [row] + + cmd = self['command'] + if callable(cmd): + cmd() + + + + def _cellframedblclick(self, event): + #print 'double click cell frame' + cmd = self['dblclickcommand'] + if callable(cmd): + cmd() + + def _celldblclick(self, event): + #print 'double click cell' + cmd = self['dblclickcommand'] + if callable(cmd): + cmd() + +if __name__ == '__main__': + + rootWin = Tkinter.Tk() + + Pmw.initialise() + + rootWin.title('MultiColumnListbox Demo') + rootWin.configure(width = 500, height = 300) + rootWin.update() + + def dbl(): + print listbox.getcurselection() + + listbox = MultiColumnListbox(rootWin, + #usehullsize = 1, + labellist = ('Column 0', + 'Column 1', + 'Column 2', + 'Column 3', + 'Column 4', + #'Column 5', + #'Column 6', + #'Column 7', + #'Column 8', + #'Column 9', + ), + horizflex = 'expand', + #vertflex = 'elastic', + dblclickcommand = dbl, + ) + + + #print 'start adding item' + for i in range(20): + r = {} + for j in range(5): + r[('Column %d'%j)] = 'Really long item name %d'%i + listbox.addrow(r) + #print 'items added' + + listbox.pack(expand = 1, fill = 'both', padx = 10, pady = 10) + + + exitButton = Tkinter.Button(rootWin, text="Quit", command=rootWin.quit) + exitButton.pack(side = 'left', padx = 10, pady = 10) + + rootWin.mainloop() diff --git a/Pmw/Pmw_1_2/contrib/PmwFileDialog.py b/Pmw/Pmw_1_2/contrib/PmwFileDialog.py new file mode 100644 index 00000000..dc7b4616 --- /dev/null +++ b/Pmw/Pmw_1_2/contrib/PmwFileDialog.py @@ -0,0 +1,498 @@ +# +__version__ = '$Id: PmwFileDialog.py,v 1.2 2002/08/23 15:03:35 gregm Exp $' +# +# Filename dialogs using Pmw +# +# (C) Rob W.W. Hooft, Nonius BV, 1998 +# +# Modifications: +# +# J. Willem M. Nissink, Cambridge Crystallographic Data Centre, 8/2002 +# Added optional information pane at top of dialog; if option +# 'info' is specified, the text given will be shown (in blue). +# Modified example to show both file and directory-type dialog +# +# No Guarantees. Distribute Freely. +# Please send bug-fixes/patches/features to +# +################################################################################ +import os,fnmatch,time +import Tkinter,Pmw +#Pmw.setversion("0.8.5") + +def _errorpop(master,text): + d=Pmw.MessageDialog(master, + title="Error", + message_text=text, + buttons=("OK",)) + d.component('message').pack(ipadx=15,ipady=15) + d.activate() + d.destroy() + +class PmwFileDialog(Pmw.Dialog): + """File Dialog using Pmw""" + def __init__(self, parent = None, **kw): + # Define the megawidget options. + optiondefs = ( + ('filter', '*', self.newfilter), + ('directory', os.getcwd(), self.newdir), + ('filename', '', self.newfilename), + ('historylen',10, None), + ('command', None, None), + ('info', None, None), + ) + self.defineoptions(kw, optiondefs) + # Initialise base class (after defining options). + Pmw.Dialog.__init__(self, parent) + + self.withdraw() + + # Create the components. + interior = self.interior() + + if self['info'] is not None: + rowoffset=1 + dn = self.infotxt() + dn.grid(row=0,column=0,columnspan=2,padx=3,pady=3) + else: + rowoffset=0 + + dn = self.mkdn() + dn.grid(row=0+rowoffset,column=0,columnspan=2,padx=3,pady=3) + del dn + + # Create the directory list component. + dnb = self.mkdnb() + dnb.grid(row=1+rowoffset,column=0,sticky='news',padx=3,pady=3) + del dnb + + # Create the filename list component. + fnb = self.mkfnb() + fnb.grid(row=1+rowoffset,column=1,sticky='news',padx=3,pady=3) + del fnb + + # Create the filter entry + ft = self.mkft() + ft.grid(row=2+rowoffset,column=0,columnspan=2,padx=3,pady=3) + del ft + + # Create the filename entry + fn = self.mkfn() + fn.grid(row=3+rowoffset,column=0,columnspan=2,padx=3,pady=3) + fn.bind('',self.okbutton) + del fn + + # Buttonbox already exists + bb=self.component('buttonbox') + bb.add('OK',command=self.okbutton) + bb.add('Cancel',command=self.cancelbutton) + del bb + + Pmw.alignlabels([self.component('filename'), + self.component('filter'), + self.component('dirname')]) + + def infotxt(self): + """ Make information block component at the top """ + return self.createcomponent( + 'infobox', + (), None, + Tkinter.Label, (self.interior(),), + width=51, + relief='groove', + foreground='darkblue', + justify='left', + text=self['info'] + ) + + def mkdn(self): + """Make directory name component""" + return self.createcomponent( + 'dirname', + (), None, + Pmw.ComboBox, (self.interior(),), + entryfield_value=self['directory'], + entryfield_entry_width=40, + entryfield_validate=self.dirvalidate, + selectioncommand=self.setdir, + labelpos='w', + label_text='Directory:') + + def mkdnb(self): + """Make directory name box""" + return self.createcomponent( + 'dirnamebox', + (), None, + Pmw.ScrolledListBox, (self.interior(),), + label_text='directories', + labelpos='n', + hscrollmode='none', + dblclickcommand=self.selectdir) + + def mkft(self): + """Make filter""" + return self.createcomponent( + 'filter', + (), None, + Pmw.ComboBox, (self.interior(),), + entryfield_value=self['filter'], + entryfield_entry_width=40, + selectioncommand=self.setfilter, + labelpos='w', + label_text='Filter:') + + def mkfnb(self): + """Make filename list box""" + return self.createcomponent( + 'filenamebox', + (), None, + Pmw.ScrolledListBox, (self.interior(),), + label_text='files', + labelpos='n', + hscrollmode='none', + selectioncommand=self.singleselectfile, + dblclickcommand=self.selectfile) + + def mkfn(self): + """Make file name entry""" + return self.createcomponent( + 'filename', + (), None, + Pmw.ComboBox, (self.interior(),), + entryfield_value=self['filename'], + entryfield_entry_width=40, + entryfield_validate=self.filevalidate, + selectioncommand=self.setfilename, + labelpos='w', + label_text='Filename:') + + def dirvalidate(self,string): + if os.path.isdir(string): + return Pmw.OK + else: + return Pmw.PARTIAL + + def filevalidate(self,string): + if string=='': + return Pmw.PARTIAL + elif os.path.isfile(string): + return Pmw.OK + elif os.path.exists(string): + return Pmw.PARTIAL + else: + return Pmw.OK + + def okbutton(self): + """OK action: user thinks he has input valid data and wants to + proceed. This is also called by in the filename entry""" + fn=self.component('filename').get() + self.setfilename(fn) + if self.validate(fn): + self.canceled=0 + self.deactivate() + + def cancelbutton(self): + """Cancel the operation""" + self.canceled=1 + self.deactivate() + + def tidy(self,w,v): + """Insert text v into the entry and at the top of the list of + the combobox w, remove duplicates""" + if not v: + return + entry=w.component('entry') + entry.delete(0,'end') + entry.insert(0,v) + list=w.component('scrolledlist') + list.insert(0,v) + index=1 + while indexself['historylen']: + list.delete(index) + else: + index=index+1 + w.checkentry() + + def setfilename(self,value): + if not value: + return + value=os.path.join(self['directory'],value) + dir,fil=os.path.split(value) + self.configure(directory=dir,filename=value) + + c=self['command'] + if callable(c): + c() + + def newfilename(self): + """Make sure a newly set filename makes it into the combobox list""" + self.tidy(self.component('filename'),self['filename']) + + def setfilter(self,value): + self.configure(filter=value) + + def newfilter(self): + """Make sure a newly set filter makes it into the combobox list""" + self.tidy(self.component('filter'),self['filter']) + self.fillit() + + def setdir(self,value): + self.configure(directory=value) + + def newdir(self): + """Make sure a newly set dirname makes it into the combobox list""" + self.tidy(self.component('dirname'),self['directory']) + self.fillit() + + def singleselectfile(self): + """Single click in file listbox. Move file to "filename" combobox""" + cs=self.component('filenamebox').curselection() + if cs!=(): + value=self.component('filenamebox').get(cs) + self.setfilename(value) + + def selectfile(self): + """Take the selected file from the filename, normalize it, and OK""" + self.singleselectfile() + value=self.component('filename').get() + self.setfilename(value) + if value: + self.okbutton() + + def selectdir(self): + """Take selected directory from the dirnamebox into the dirname""" + cs=self.component('dirnamebox').curselection() + if cs!=(): + value=self.component('dirnamebox').get(cs) + dir=self['directory'] + if not dir: + dir=os.getcwd() + if value: + if value=='..': + dir=os.path.split(dir)[0] + else: + dir=os.path.join(dir,value) + self.configure(directory=dir) + self.fillit() + + def askfilename(self,directory=None,filter=None): + """The actual client function. Activates the dialog, and + returns only after a valid filename has been entered + (return value is that filename) or when canceled (return + value is None)""" + if directory!=None: + self.configure(directory=directory) + if filter!=None: + self.configure(filter=filter) + self.fillit() + self.canceled=1 # Needed for when user kills dialog window + self.activate() + if self.canceled: + return None + else: + return self.component('filename').get() + + lastdir="" + lastfilter=None + lasttime=0 + def fillit(self): + """Get the directory list and show it in the two listboxes""" + # Do not run unnecesarily + if self.lastdir==self['directory'] and self.lastfilter==self['filter'] and self.lasttime>os.stat(self.lastdir)[8]: + return + self.lastdir=self['directory'] + self.lastfilter=self['filter'] + self.lasttime=time.time() + dir=self['directory'] + if not dir: + dir=os.getcwd() + dirs=['..'] + files=[] + try: + fl=os.listdir(dir) + fl.sort() + except os.error,arg: + if arg[0] in (2,20): + return + raise + for f in fl: + if os.path.isdir(os.path.join(dir,f)): + dirs.append(f) + else: + filter=self['filter'] + if not filter: + filter='*' + if fnmatch.fnmatch(f,filter): + files.append(f) + self.component('filenamebox').setlist(files) + self.component('dirnamebox').setlist(dirs) + + def validate(self,filename): + """Validation function. Should return 1 if the filename is valid, + 0 if invalid. May pop up dialogs to tell user why. Especially + suited to subclasses: i.e. only return 1 if the file does/doesn't + exist""" + return 1 + +class PmwDirDialog(PmwFileDialog): + """Directory Dialog using Pmw""" + def __init__(self, parent = None, **kw): + # Define the megawidget options. + optiondefs = ( + ('directory', os.getcwd(), self.newdir), + ('historylen',10, None), + ('command', None, None), + ('info', None, None), + ) + self.defineoptions(kw, optiondefs) + # Initialise base class (after defining options). + Pmw.Dialog.__init__(self, parent) + + self.withdraw() + + # Create the components. + interior = self.interior() + + if self['info'] is not None: + rowoffset=1 + dn = self.infotxt() + dn.grid(row=0,column=0,columnspan=2,padx=3,pady=3) + else: + rowoffset=0 + + dn = self.mkdn() + dn.grid(row=1+rowoffset,column=0,columnspan=2,padx=3,pady=3) + dn.bind('',self.okbutton) + del dn + + # Create the directory list component. + dnb = self.mkdnb() + dnb.grid(row=0+rowoffset,column=0,columnspan=2,sticky='news',padx=3,pady=3) + del dnb + + # Buttonbox already exists + bb=self.component('buttonbox') + bb.add('OK',command=self.okbutton) + bb.add('Cancel',command=self.cancelbutton) + del bb + + lastdir="" + def fillit(self): + """Get the directory list and show it in the two listboxes""" + # Do not run unnecesarily + if self.lastdir==self['directory']: + return + self.lastdir=self['directory'] + dir=self['directory'] + if not dir: + dir=os.getcwd() + dirs=['..'] + try: + fl=os.listdir(dir) + fl.sort() + except os.error,arg: + if arg[0] in (2,20): + return + raise + for f in fl: + if os.path.isdir(os.path.join(dir,f)): + dirs.append(f) + self.component('dirnamebox').setlist(dirs) + + def okbutton(self): + """OK action: user thinks he has input valid data and wants to + proceed. This is also called by in the dirname entry""" + fn=self.component('dirname').get() + self.configure(directory=fn) + if self.validate(fn): + self.canceled=0 + self.deactivate() + + def askfilename(self,directory=None): + """The actual client function. Activates the dialog, and + returns only after a valid filename has been entered + (return value is that filename) or when canceled (return + value is None)""" + if directory!=None: + self.configure(directory=directory) + self.fillit() + self.activate() + if self.canceled: + return None + else: + return self.component('dirname').get() + + def dirvalidate(self,string): + if os.path.isdir(string): + return Pmw.OK + elif os.path.exists(string): + return Pmw.PARTIAL + else: + return Pmw.OK + + def validate(self,filename): + """Validation function. Should return 1 if the filename is valid, + 0 if invalid. May pop up dialogs to tell user why. Especially + suited to subclasses: i.e. only return 1 if the file does/doesn't + exist""" + if filename=='': + _errorpop(self.interior(),"Empty filename") + return 0 + if os.path.isdir(filename) or not os.path.exists(filename): + return 1 + else: + _errorpop(self.interior(),"This is not a directory") + return 0 + +class PmwExistingFileDialog(PmwFileDialog): + def filevalidate(self,string): + if os.path.isfile(string): + return Pmw.OK + else: + return Pmw.PARTIAL + + def validate(self,filename): + if os.path.isfile(filename): + return 1 + elif os.path.exists(filename): + _errorpop(self.interior(),"This is not a plain file") + return 0 + else: + _errorpop(self.interior(),"Please select an existing file") + return 0 + +class PmwExistingDirDialog(PmwDirDialog): + def dirvalidate(self,string): + if os.path.isdir(string): + return Pmw.OK + else: + return Pmw.PARTIAL + + def validate(self,filename): + if os.path.isdir(filename): + return 1 + elif os.path.exists(filename): + _errorpop(self.interior(),"This is not a directory") + return 0 + else: + _errorpop(self.interior(),"Please select an existing directory") + +if __name__=="__main__": + root=Tkinter.Tk() + root.withdraw() + Pmw.initialise() + + f0=PmwFileDialog(root) + f0.title('File name dialog') + n=f0.askfilename() + print '\nFilename : ',repr(n),'\n' + + f1=PmwDirDialog(root,info='This is a directory dialog') + f1.title('Directory name dialog') + while 1: + n=f1.askfilename() + if n is None: + break + print "Dirname : ",repr(n) diff --git a/Pmw/Pmw_1_2/contrib/PmwFullTimeCounter.py b/Pmw/Pmw_1_2/contrib/PmwFullTimeCounter.py new file mode 100644 index 00000000..84e605a3 --- /dev/null +++ b/Pmw/Pmw_1_2/contrib/PmwFullTimeCounter.py @@ -0,0 +1,492 @@ +# Authors: Joe VanAndel, Greg McFarlane and Daniel Michelson + +import string +import sys +import time +import Tkinter +import Pmw + +class FullTimeCounter(Pmw.MegaWidget): + """Up-down counter + + A TimeCounter is a single-line entry widget with Up and Down arrows + which increment and decrement the Time value in the entry. + """ + + def __init__(self, parent = None, **kw): + + # Define the megawidget options. + INITOPT = Pmw.INITOPT + optiondefs = ( + ('autorepeat', 1, INITOPT), + ('buttonaspect', 1.0, INITOPT), + ('initwait', 300, INITOPT), + ('labelmargin', 0, INITOPT), + ('labelpos', None, INITOPT), + ('max', '', self._max), + ('min', '', self._min), + ('padx', 0, INITOPT), + ('pady', 0, INITOPT), + ('repeatrate', 50, INITOPT), + ('value', '', INITOPT), + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaWidget.__init__(self, parent) + + self.arrowDirection = {} + self._flag = 'stopped' + self._timerId = None + + self._createComponents() + + value = self['value'] + if value is None or value == '': + now = time.time() + value = time.strftime('%Y:%m:%d:%H:%M',time.gmtime(now)) + self._setTimeFromStr(value) + + # Check keywords and initialise options. + self.initialiseoptions() + + def _createComponents(self): + + # Create the components. + interior = self.interior() + + # If there is no label, put the arrows and the entry directly + # into the interior, otherwise create a frame for them. In + # either case the border around the arrows and the entry will + # be raised (but not around the label). + if self['labelpos'] is None: + frame = interior + else: + frame = self.createcomponent('frame', + (), None, + Tkinter.Frame, (interior,)) + frame.grid(column=2, row=2, sticky='nsew') + interior.grid_columnconfigure(2, weight=1) + interior.grid_rowconfigure(2, weight=1) + + frame.configure(relief = 'raised', borderwidth = 1) + + # Create the down arrow buttons. + + # Create the year down arrow. + self._downYearArrowBtn = self.createcomponent('downyeararrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._downYearArrowBtn] = 0 + self._downYearArrowBtn.grid(column = 0, row = 2) + + # Create the month down arrow. + self._downMonthArrowBtn = self.createcomponent('downmontharrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._downMonthArrowBtn] = 0 + self._downMonthArrowBtn.grid(column = 1, row = 2) + + # Create the day down arrow. + self._downDayArrowBtn = self.createcomponent('downdayarrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._downDayArrowBtn] = 0 + self._downDayArrowBtn.grid(column = 2, row = 2) + + # Create the hour down arrow. + self._downHourArrowBtn = self.createcomponent('downhourarrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._downHourArrowBtn] = 0 + self._downHourArrowBtn.grid(column = 3, row = 2) + + # Create the minute down arrow. + self._downMinuteArrowBtn = self.createcomponent('downminutearrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._downMinuteArrowBtn] = 0 + self._downMinuteArrowBtn.grid(column = 4, row = 2) + + # Create the entry fields. + + # Create the year entry field. + self._yearCounterEntry = self.createcomponent('yearentryfield', + (('yearentry', 'yearentryfield_entry'),), None, + Pmw.EntryField, (frame,), validate='integer', entry_width = 4) + self._yearCounterEntry.grid(column = 0, row = 1, sticky = 'news') + + # Create the month entry field. + self._monthCounterEntry = self.createcomponent('monthentryfield', + (('monthentry', 'monthentryfield_entry'),), None, + Pmw.EntryField, (frame,), validate='integer', entry_width = 2) + self._monthCounterEntry.grid(column = 1, row = 1, sticky = 'news') + + # Create the day entry field. + self._dayCounterEntry = self.createcomponent('dayentryfield', + (('dayentry', 'dayentryfield_entry'),), None, + Pmw.EntryField, (frame,), validate='integer', entry_width = 2) + self._dayCounterEntry.grid(column = 2, row = 1, sticky = 'news') + + # Create the hour entry field. + self._hourCounterEntry = self.createcomponent('hourentryfield', + (('hourentry', 'hourentryfield_entry'),), None, + Pmw.EntryField, (frame,), validate='integer', entry_width = 2) + self._hourCounterEntry.grid(column = 3, row = 1, sticky = 'news') + + # Create the minute entry field. + self._minuteCounterEntry = self.createcomponent('minuteentryfield', + (('minuteentry', 'minuteentryfield_entry'),), None, + Pmw.EntryField, (frame,), validate='integer', entry_width = 2) + self._minuteCounterEntry.grid(column = 4, row = 1, sticky = 'news') + + # Create the up arrow buttons. + + # Create the year up arrow. + self._upYearArrowBtn = self.createcomponent('upyeararrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._upYearArrowBtn] = 1 + self._upYearArrowBtn.grid(column = 0, row = 0) + + # Create the month up arrow. + self._upMonthArrowBtn = self.createcomponent('upmontharrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._upMonthArrowBtn] = 1 + self._upMonthArrowBtn.grid(column = 1, row = 0) + + # Create the day up arrow. + self._upDayArrowBtn = self.createcomponent('updayarrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._upDayArrowBtn] = 1 + self._upDayArrowBtn.grid(column = 2, row = 0) + + # Create the hour up arrow. + self._upHourArrowBtn = self.createcomponent('uphourarrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._upHourArrowBtn] = 1 + self._upHourArrowBtn.grid(column = 3, row = 0) + + # Create the minute up arrow. + self._upMinuteArrowBtn = self.createcomponent('upminutearrow', + (), 'Arrow', + Tkinter.Canvas, (frame,), + width = 16, height = 16, relief = 'raised', borderwidth = 2) + self.arrowDirection[self._upMinuteArrowBtn] = 1 + self._upMinuteArrowBtn.grid(column = 4, row = 0) + + # Make it resize nicely. + padx = self['padx'] + pady = self['pady'] + for col in range(5): # YY, MM, DD, HH, mm + frame.grid_columnconfigure(col, weight = 1, pad = padx) + frame.grid_rowconfigure(0, pad = pady) + frame.grid_rowconfigure(2, pad = pady) + + frame.grid_rowconfigure(1, weight = 1) + + # Create the label. + self.createlabel(interior) + + # Set bindings. + + # Up year + self._upYearArrowBtn.bind('', + lambda event, s=self,button=self._upYearArrowBtn: + s._drawArrow(button, 1)) + self._upYearArrowBtn.bind('<1>', + lambda event, s=self,button=self._upYearArrowBtn: + s._countUp(button)) + self._upYearArrowBtn.bind('', + lambda event, s=self, button=self._upYearArrowBtn: + s._stopUpDown(button)) + + # Up month + self._upMonthArrowBtn.bind('', + lambda event, s=self,button=self._upMonthArrowBtn: + s._drawArrow(button, 1)) + self._upMonthArrowBtn.bind('<1>', + lambda event, s=self,button=self._upMonthArrowBtn: + s._countUp(button)) + self._upMonthArrowBtn.bind('', + lambda event, s=self, button=self._upMonthArrowBtn: + s._stopUpDown(button)) + + # Up day + self._upDayArrowBtn.bind('', + lambda event, s=self,button=self._upDayArrowBtn: + s._drawArrow(button, 1)) + self._upDayArrowBtn.bind('<1>', + lambda event, s=self,button=self._upDayArrowBtn: + s._countUp(button)) + self._upDayArrowBtn.bind('', + lambda event, s=self, button=self._upDayArrowBtn: + s._stopUpDown(button)) + + # Up hour + self._upHourArrowBtn.bind('', + lambda event, s=self,button=self._upHourArrowBtn: + s._drawArrow(button, 1)) + self._upHourArrowBtn.bind('<1>', + lambda event, s=self,button=self._upHourArrowBtn: + s._countUp(button)) + self._upHourArrowBtn.bind('', + lambda event, s=self, button=self._upHourArrowBtn: + s._stopUpDown(button)) + + # Up minute + self._upMinuteArrowBtn.bind('', + lambda event, s=self,button=self._upMinuteArrowBtn: + s._drawArrow(button, 1)) + self._upMinuteArrowBtn.bind('<1>', + lambda event, s=self,button=self._upMinuteArrowBtn: + s._countUp(button)) + self._upMinuteArrowBtn.bind('', + lambda event, s=self, button=self._upMinuteArrowBtn: + s._stopUpDown(button)) + + + # Down year + self._downYearArrowBtn.bind('', + lambda event, s=self,button=self._downYearArrowBtn: + s._drawArrow(button, 0)) + self._downYearArrowBtn.bind('<1>', + lambda event, s=self,button=self._downYearArrowBtn: + s._countDown(button)) + self._downYearArrowBtn.bind('', + lambda event, s=self, button=self._downYearArrowBtn: + s._stopUpDown(button)) + + # Down month + self._downMonthArrowBtn.bind('', + lambda event, s=self,button=self._downMonthArrowBtn: + s._drawArrow(button, 0)) + self._downMonthArrowBtn.bind('<1>', + lambda event, s=self,button=self._downMonthArrowBtn: + s._countDown(button)) + self._downMonthArrowBtn.bind('', + lambda event, s=self, button=self._downMonthArrowBtn: + s._stopUpDown(button)) + + # Down day + self._downDayArrowBtn.bind('', + lambda event, s=self,button=self._downDayArrowBtn: + s._drawArrow(button, 0)) + self._downDayArrowBtn.bind('<1>', + lambda event, s=self,button=self._downDayArrowBtn: + s._countDown(button)) + self._downDayArrowBtn.bind('', + lambda event, s=self, button=self._downDayArrowBtn: + s._stopUpDown(button)) + + # Down hour + self._downHourArrowBtn.bind('', + lambda event, s=self,button=self._downHourArrowBtn: + s._drawArrow(button, 0)) + self._downHourArrowBtn.bind('<1>', + lambda event, s=self,button=self._downHourArrowBtn: + s._countDown(button)) + self._downHourArrowBtn.bind('', + lambda event, s=self, button=self._downHourArrowBtn: + s._stopUpDown(button)) + + # Down minute + self._downMinuteArrowBtn.bind('', + lambda event, s=self,button=self._downMinuteArrowBtn: + s._drawArrow(button, 0)) + self._downMinuteArrowBtn.bind('<1>', + lambda event, s=self,button=self._downMinuteArrowBtn: s._countDown(button)) + self._downMinuteArrowBtn.bind('', + lambda event, s=self, button=self._downMinuteArrowBtn: + s._stopUpDown(button)) + + + self._yearCounterEntry.bind('', self.invoke) + self._monthCounterEntry.bind('', self.invoke) + self._dayCounterEntry.bind('', self.invoke) + self._hourCounterEntry.bind('', self.invoke) + self._minuteCounterEntry.bind('', self.invoke) + + self._yearCounterEntry.bind('', self._resizeArrow) + self._monthCounterEntry.bind('', self._resizeArrow) + self._dayCounterEntry.bind('', self._resizeArrow) + self._hourCounterEntry.bind('', self._resizeArrow) + self._minuteCounterEntry.bind('', self._resizeArrow) + + def _drawArrow(self, arrow, direction): + arrow.delete('arrow') + + fg = self._yearCounterEntry.cget('entry_foreground') + + bw = (string.atoi(arrow['borderwidth']) + + string.atoi(arrow['highlightthickness'])) / 2 + h = string.atoi(arrow['height']) + 2 * bw + w = string.atoi(arrow['width']) + 2 * bw + + if direction == 0: + # down arrow + arrow.create_polygon( + 0.25 * w + bw, 0.25 * h + bw, + 0.50 * w + bw, 0.75 * h + bw, + 0.75 * w + bw, 0.25 * h + bw, + fill=fg, tag='arrow') + else: + arrow.create_polygon( + 0.25 * w + bw, 0.75 * h + bw, + 0.50 * w + bw, 0.25 * h + bw, + 0.75 * w + bw, 0.75 * h + bw, + fill=fg, tag='arrow') + + def _resizeArrow(self, event = None): + for btn in (self._upYearArrowBtn, self._upMonthArrowBtn, + self._upDayArrowBtn, self._upHourArrowBtn, + self._upMinuteArrowBtn, self._downYearArrowBtn, + self._downMonthArrowBtn, self._downDayArrowBtn, + self._downHourArrowBtn, self._downMinuteArrowBtn): + bw = (string.atoi(btn['borderwidth']) + \ + string.atoi(btn['highlightthickness'])) + newHeight = self._yearCounterEntry.winfo_reqheight() - 2 * bw + newWidth = newHeight * self['buttonaspect'] + btn.configure(width=newWidth, height=newHeight) + self._drawArrow(btn, self.arrowDirection[btn]) + + def _min(self): + self._minVal = None + + def _max(self): + self._maxVal = None + + def _setTimeFromStr(self, str): + list = string.split(str, ':') + if len(list) != 5: + raise ValueError, 'invalid value: ' + str + + self._year = string.atoi(list[0]) + self._month = string.atoi(list[1]) + self._day = string.atoi(list[2]) + self._hour = string.atoi(list[3]) + self._minute = string.atoi(list[4]) + + self._setHMS() + + def getstring(self): + return '%04d:%02d:%02d:%02d:%02d' % (self._year, self._month, + self._day, self._hour, + self._minute) + + def getint(self): + pass + + def _countUp(self, button): + self._relief = self._upYearArrowBtn.cget('relief') + button.configure(relief='sunken') + if button == self._upYearArrowBtn: datetype = "year" + elif button == self._upMonthArrowBtn: datetype = "month" + elif button == self._upDayArrowBtn: datetype = "day" + elif button == self._upHourArrowBtn: datetype = "hour" + elif button == self._upMinuteArrowBtn: datetype = "minute" + self._count(1, datetype, 'start') + + def _countDown(self, button): + self._relief = self._downYearArrowBtn.cget('relief') + button.configure(relief='sunken') + if button == self._downYearArrowBtn: datetype = "year" + elif button == self._downMonthArrowBtn: datetype = "month" + elif button == self._downDayArrowBtn: datetype = "day" + elif button == self._downHourArrowBtn: datetype = "hour" + elif button == self._downMinuteArrowBtn: datetype = "minute" + self._count(-1, datetype, 'start') + + def _count(self, factor, datetype, newFlag=None): + if newFlag != 'force': + if newFlag is not None: + self._flag = newFlag + + if self._flag == 'stopped': + return + + if datetype == "year": self._year = self._year + factor + elif datetype == "month": self._month = self._month + factor + elif datetype == "day": self._day = self._day + factor + elif datetype == "hour": self._hour = self._hour + factor + elif datetype == "minute": self._minute = self._minute + factor + secs = time.mktime((self._year, self._month, self._day, self._hour, + self._minute, 0, 0, 0, -1)) + tt = time.localtime(secs) # NOT gmtime! + + self._year = tt[0] + self._month = tt[1] + self._day = tt[2] + self._hour = tt[3] + self._minute = tt[4] + self._setHMS() + + if newFlag != 'force': + if self['autorepeat']: + if self._flag == 'start': + delay = self['initwait'] + self._flag = 'running' + else: + delay = self['repeatrate'] + self._timerId = self.after( + delay, lambda self=self, factor=factor, datetype=datetype: + self._count(factor, datetype, 'running')) + + def _setHMS(self): + self._yearCounterEntry.setentry('%04d' % self._year) + self._monthCounterEntry.setentry('%02d' % self._month) + self._dayCounterEntry.setentry('%02d' % self._day) + self._hourCounterEntry.setentry('%02d' % self._hour) + self._minuteCounterEntry.setentry('%02d' % self._minute) + + def _stopUpDown(self, button): + if self._timerId is not None: + self.after_cancel(self._timerId) + self._timerId = None + button.configure(relief=self._relief) + self._flag = 'stopped' + + def invoke(self, event = None): + cmd = self['command'] + if callable(cmd): + cmd() + + def destroy(self): + if self._timerId is not None: + self.after_cancel(self._timerId) + self._timerId = None + Pmw.MegaWidget.destroy(self) + +if __name__=="__main__": + + def showString(): + stringVal = _time.getstring() + print stringVal + + root = Tkinter.Tk() + Pmw.initialise(root) + root.title('FullTimeCounter') + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + + _time = FullTimeCounter(root, + labelpos = 'n', + label_text = 'YYYY:MM:DD:HH:mm') + _time.pack(fill = 'both', expand = 1, padx=10, pady=5) + + button = Tkinter.Button(root, text = 'Show', command = showString) + button.pack() + root.mainloop() diff --git a/Pmw/Pmw_1_2/contrib/PmwVerticalGauge.py b/Pmw/Pmw_1_2/contrib/PmwVerticalGauge.py new file mode 100644 index 00000000..b413f937 --- /dev/null +++ b/Pmw/Pmw_1_2/contrib/PmwVerticalGauge.py @@ -0,0 +1,253 @@ +""" +I needed a simple gauge, so I've made on with Pmw. +It might be useful for others to use as a base to develop more comples +gauges with. + +Is it worth cleaning up and submitting? + +cheers and thanks + +chris + +Dr. Chris Wright +Intensive Care Unit +Monash Medical Centre +Clayton. VIC Australia +""" + +import sys +import Tkinter +import Pmw +import time + + +if sys.platform == 'win32': + # MS-Windows specific fonts + label_font = "-family Ariel -size 12" + value_font = "-family Ariel -size 12" + small_font = "-family {MS Sans Serif} -size 9 -weight bold" + header_font = "-family {MS Sans Serif} -weight bold" +else: + # X-Windows specific fonts + label_font = "-*-helvetica-*-r-*-*-*-160-*-*-*-*-*-*" + value_font = "-*-courier-*-r-*-*-*-160-*-*-*-*-*-*" + small_font = "-*-helvetica-*-r-*-*-*-130-*-*-*-*-*-*" + header_font = "-*-helvetica-bold-r-*-*-*-150-*-*-*-*-*-*" + +class VerticalGauge(Pmw.MegaWidget): + """Vertical gauge with actual and desired settings""" + + def __init__(self, parent = None, **kw): + optiondefs = ( + ('min', 0, None), + ('max', 100, None), + ('majortickinterval', 10, None), + ('minortickinterval', 5, None), + ('units', '', None), + ('bg', 'grey', self._backgroundSet), + ('actualvalue', 50, self._actualSet), + ('desiredvalue', 50, self._desiredSet), + ('actualcolour', 'yellow1', None), + ('desiredcolour', 'turquoise1', None), + ('label', 'Label', None), + ) + self.defineoptions(kw, optiondefs) + Pmw.MegaWidget.__init__(self, parent) + + interior = self.interior() + interior.grid_rowconfigure(1, weight = 1) + for r in range(3): + interior.grid_columnconfigure(r, weight = 1) + + self.actuallabel = self.createcomponent('actualLabel', + (), None, + Tkinter.Label, (interior,), + text = '', + width = 3, + relief = 'sunken', + bd = 1, + fg = self['actualcolour'], + font = value_font) + self.actuallabel.grid(sticky = "nswe", row = 0, column = 0) + + self.label = self.createcomponent('label', + (), None, + Tkinter.Label, (interior,), + text = self['label'], + relief = 'raised', + font = label_font, + fg = 'navy', + bd = 2) + self.label.grid(sticky = "nsew", row = 0, column = 1) + + self.desiredlabel = self.createcomponent('desiredLabel', + (), None, + Tkinter.Label, (interior,), + text = '', + width = 3, + relief = 'sunken', + bd = 1, + fg = self['desiredcolour'], + font = value_font) + self.desiredlabel.grid(sticky = "nswe", row = 0, column = 2) + + self.canvas = self.createcomponent('canvas', + (), None, + Tkinter.Canvas, (interior,), + width = 100, + height = 300, + bg = 'grey') + + self.canvas.grid(sticky = "nsew", columnspan = 3, pady = 1) + self.canvas.bind("", self._createGaugeAxes) + + self._createGaugeAxes() + + self.initialiseoptions() + + def _createGaugeAxes(self, event = None): + min = self['min'] + max = self['max'] + units = self['units'] + majortickinterval = self['majortickinterval'] + + gauge_range = max - min + + c = self.canvas + c.delete("all") + if event: + h, w = event.height, event.width + else: + h = int(c.configure("height")[4]) + w = int(c.configure("width")[4]) + + self.lower = h - 15 + self.upper = 15 + self.middle = w / 2 + c.create_line(self.middle, self.lower, self.middle, self.upper) + + majortickcount = int((max - min) / majortickinterval) + self.axislength = self.lower - self.upper + self.majortickdistance = float(self.axislength) / majortickcount + self.majortickwidth = w / 5 + labeloffset = (w / 4) + 10 + + for i in range(majortickcount + 1): + v = min + i * majortickinterval + d = self.lower - i * self.majortickdistance + c.create_line(self.middle, d, self.middle + self.majortickwidth, d) + c.create_text(self.middle + labeloffset, d, font = small_font, text = str(v)) + + self._desiredSet(event) + self._actualSet(event) + + def _backgroundSet(self): + self.canvas.configure(bg = self['bg']) + + def _desiredSet(self, event = None): + c = self.canvas + desired = self['desiredvalue'] + desiredcolour = self['desiredcolour'] + + min = self['min'] + max = self['max'] + + if desired > max: desired = max + if desired < min: desired = min + gauge_range = max - min + + c = self.canvas + if event: + h, w = event.height, event.width + else: + h = int(c.configure("height")[4]) + w = int(c.configure("width")[4]) + + + desired_y = self.lower - (float(desired - min) / gauge_range) * self.axislength + + try: + c.delete('desiredBar') + except: + pass + + c.create_line(self.middle - self.majortickwidth, desired_y, + self.middle + self.majortickwidth, desired_y, + fill = desiredcolour, stipple = 'gray50', + width = 10, tag = 'desiredBar') + self.desiredlabel.configure(text = desired) + + def setActual(self, value): + self.configure(actualvalue = value) + + def getActual(self): + return self.cget('actualvalue') + + def _actualSet(self, event = None): + c = self.canvas + actual = self['actualvalue'] + actualcolour = self['actualcolour'] + + min = self['min'] + max = self['max'] + + if actual > max: actual = max + if actual < min: actual = min + gauge_range = max - min + + c = self.canvas + if event: + h, w = event.height, event.width + else: + h = int(c.configure("height")[4]) + w = int(c.configure("width")[4]) + + actual_y = self.lower - (float(actual - min) / gauge_range) * self.axislength + + try: + c.delete('actualPointer') + except: + pass + + triangle = ((self.middle, actual_y), + (self.middle - 1.4 * self.majortickwidth, actual_y - self.majortickwidth / 2), + (self.middle - 1.4 * self.majortickwidth, actual_y + self.majortickwidth / 2)) + + c.create_polygon(triangle, fill = actualcolour, tag = 'actualPointer') + self.actuallabel.configure(text = actual) + + +Pmw.forwardmethods(VerticalGauge, Tkinter.Canvas, 'canvas') + +if __name__ == '__main__': + + + # Initialise Tkinter and Pmw. + root = Pmw.initialise() + root.title('Pmw VerticalGauge demonstration') + + + def increase(): + av = g1.getActual() + g1.setActual(av + 1) + + def decrease(): + av = g1.getActual() + g1.setActual(av - 1) + + g1 = VerticalGauge(min = 0, + max = 30, + actualvalue = 15, + desiredvalue = 22, + majortickinterval = 2, + label = "Pms") + g1.grid(sticky = "nsew") + root.grid_rowconfigure(0, weight = 1) + root.grid_columnconfigure(0, weight = 1) + b1 = Tkinter.Button(text = "Increase", command = increase) + b1.grid() + b2 = Tkinter.Button(text = "Decrease", command = decrease) + b2.grid() + + # Let's go. + root.mainloop() diff --git a/Pmw/Pmw_1_2/contrib/README b/Pmw/Pmw_1_2/contrib/README new file mode 100644 index 00000000..2662f77e --- /dev/null +++ b/Pmw/Pmw_1_2/contrib/README @@ -0,0 +1,10 @@ +This directory contains contributed Pmw megawidgets. + +DirBrowser.py directory selection dialog +MCListbox.py multi-column selectable listbox +PmwFileDialog.py file selection dialog +PmwFullTimeCounter.py time counter which includes year, month and day +PmwVerticalGauge.py a simple gauge indicating a value and a threshold +TreeBrowser.py generic hierarchical tree browser + +Each file can be executed and will display a demo of its megawidget. diff --git a/Pmw/Pmw_1_2/contrib/TreeBrowser.py b/Pmw/Pmw_1_2/contrib/TreeBrowser.py new file mode 100644 index 00000000..6d9fe89a --- /dev/null +++ b/Pmw/Pmw_1_2/contrib/TreeBrowser.py @@ -0,0 +1,732 @@ +# +# FILE: TreeBrowser.py +# +# DESCRIPTION: +# This file provides a generic hierarchical tree browser widget. +# +# AUTHOR: Steve Kinneberg , +# MontaVista Software, Inc. +# +# Copyright 2001 MontaVista Software Inc. +# +# This program 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 2 of the License, or (at your +# option) any later version. +# +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +# NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 675 Mass Ave, Cambridge, MA 02139, USA. +# + + +import types +import Tkinter +import Pmw + + +class _Branching: + def __init__(self): + # List of branch names + self._nodeNames = [] + + # Map from branch name to branch info + # branch Either _LeafNode or _BranchNode widget of the branch + # nodetype Either 'TreeNode' or 'LeafNode' + self._nodeAttrs = {} + + def addbranch(self, branchName = None, **kw): + kw['indent'] = self['indent'] + return apply(self._insertnode, + ('tree', branchName, len(self._nodeNames), + self._treeRoot), + kw) + + def addleaf(self, leafName = None, **kw): + return apply(self._insertnode, + ('leaf', leafName, len(self._nodeNames), + self._treeRoot), + kw) + + def insertbranch(self, branchName = None, before = 0, **kw): + kw['indent'] = self['indent'] + return apply(self._insertnode, + ('tree', branchName, before, self._treeRoot), + kw) + + def insertleaf(self, leafName = None, before = 0, **kw): + return apply(self._insertnode, + ('leaf', leafName, before, self._treeRoot), + kw) + + def _insertnode(self, type, nodeName, before, treeRoot, **kw): + if 'selectbackground' not in kw.keys(): + kw['selectbackground'] = self['selectbackground'] + + if 'selectforeground' not in kw.keys(): + kw['selectforeground'] = self['selectforeground'] + + if 'background' not in kw.keys(): + kw['background'] = self['background'] + + if 'foreground' not in kw.keys(): + kw['foreground'] = self['foreground'] + + if nodeName == None: + nodeName = self._nodeName + ".%d" % (len(self._nodeNames) + 1) + + if self._nodeAttrs.has_key(nodeName): + msg = 'Node "%s" already exists.' % nodeName + raise ValueError, msg + + # Do this early to catch bad spec before creating any items. + beforeIndex = self.index(before, 1) + attributes = {} + + last = (beforeIndex == len(self._nodeNames)) + if last and len(self._nodeNames) > 0: + # set the previous node to not last + self._nodeAttrs[self._nodeNames[-1]]['branch']._setlast(0) + + if(type == 'tree'): + node = apply(self.createcomponent, ('branch%d'%len(self._nodeNames), + (), None, + _BranchNode, + self._branchFrame, + nodeName, + treeRoot, + self, + last, + ), kw) + attributes['nodetype'] = 'TreeNode' + else: + node = apply(self.createcomponent, ('leaf%d'%len(self._nodeNames), + (), None, + _LeafNode, + self._branchFrame, + nodeName, + treeRoot, + self, + last, + ), kw) + attributes['nodetype'] = 'LeafNode' + + if len(self._nodeNames) == beforeIndex: + node.pack(anchor='w') + else: + bname = self._nodeNames[beforeIndex] + battrs = self._nodeAttrs[bname] + node.pack(anchor='w', before=battrs['branch']) + + attributes['branch'] = node + + self._nodeAttrs[nodeName] = attributes + self._nodeNames.insert(beforeIndex, nodeName) + self._sizechange() + return node + + def delete(self, *nodes): + curSel = self._treeRoot.curselection()[0] + for node in nodes: + index = self.index(node) + name = self._nodeNames.pop(index) + dnode = self._nodeAttrs[name]['branch'] + del self._nodeAttrs[name] + if dnode == curSel: + self._treeRoot._unhightlightnode(dnode) + dnode.destroy() + self._sizechange() + + def destroy(self): + for node in len(self._nodeNames): + self.delete(node) + Pmw.MegaWidget.destroy(self) + + def index(self, index, forInsert = 0): + if isinstance(index, _LeafNode): + index = index._nodeName + listLength = len(self._nodeNames) + if type(index) == types.IntType: + if forInsert and index <= listLength: + return index + elif not forInsert and index < listLength: + return index + else: + raise ValueError, 'index "%s" is out of range' % index + elif type(index) == types.StringType: + if index in self._nodeNames: + return self._nodeNames.index(index) + raise ValueError, 'bad branch or leaf name: %s' % index + elif index is Pmw.END: + if forInsert: + return listLength + elif listLength > 0: + return listLength - 1 + else: + raise ValueError, 'TreeNode has no branches' + #elif index is Pmw.SELECT: + # if listLength == 0: + # raise ValueError, 'TreeNode has no branches' + # return self._pageNames.index(self.getcurselection()) + else: + validValues = 'a name, a number, Pmw.END, Pmw.SELECT, or a reference to a TreeBrowser Leaf or Branch' + raise ValueError, \ + 'bad index "%s": must be %s' % (index, validValues) + + def getnodenames(self): + return self._nodeNames + + def getnode(self, node): + nodeName = self._nodeNames[self.index(node)] + return self._nodeAttrs[nodeName]['branch'] + + +class _LeafNode(Pmw.MegaWidget): + + def __init__(self, parent, nodeName, treeRoot, parentnode, last = 1, **kw): + colors = Pmw.Color.getdefaultpalette(parent) + + self._nodeName = nodeName + self._treeRoot = treeRoot + self._parentNode = parentnode + + self._last = last + # Define the megawidget options. + INITOPT = Pmw.INITOPT + optiondefs = ( + ('selectbackground', colors['selectBackground'], INITOPT), + ('selectforeground', colors['selectForeground'], INITOPT), + ('background', colors['background'], INITOPT), + ('foreground', colors['foreground'], INITOPT), + ('selectcommand', None, None), + ('deselectcommand', None, None), + ('labelpos', 'e', INITOPT), + ('labelmargin', 0, INITOPT), + ('label', None, None), + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaWidget.__init__(self, parent) + + # Create the components + interior = self._hull + + + labelpos = self['labelpos'] + + if self['label'] == None: + self._labelWidget = self.createcomponent('labelwidget', + (), None, + Pmw.LabeledWidget, + (interior,), + #background = self['background'], + #foreground = self['foreground'], + ) + else: + self._labelWidget = self.createcomponent('labelwidget', + (), None, + Pmw.LabeledWidget, + (interior,), + label_background = self['background'], + label_foreground = self['foreground'], + labelpos = labelpos, + labelmargin = self['labelmargin'], + label_text = self['label'], + ) + self._labelWidget.component('label').bind('', + self._selectevent) + + self._labelWidget.grid(column = 1, row = 0, sticky = 'w') + + self._labelWidget.update() + + self._labelheight = self._labelWidget.winfo_height() + + self._lineCanvas = self.createcomponent('linecanvas', + (), None, + Tkinter.Canvas, + (interior,), + width = self._labelheight, + height = self._labelheight, + ) + self._lineCanvas.grid( column = 0, row = 0, sticky = 'news') + self._lineCanvas.update() + + cw = int(self._lineCanvas['width']) + ch = int(self._lineCanvas['height']) + + self._lineCanvas.create_line(cw/2, ch/2, cw, ch/2, tag='hline') + if last: + self._lineCanvas.create_line(cw/2, 0, cw/2, ch/2, tag='vline') + else: + self._lineCanvas.create_line(cw/2, 0, cw/2, ch, tag='vline') + + # Check keywords and initialise options. + self.initialiseoptions() + + + def interior(self): + return self._labelWidget.interior() + + def select(self): + self._highlight() + + def getname(self): + return self._nodeName + + def getlabel(self): + return self['label'] + + def _selectevent(self, event): + self._highlight() + + def _highlight(self): + self._treeRoot._highlightnode(self) + #self._subHull.configure(background = self._selectbg, relief = 'raised') + if self['label'] != None: + self._labelWidget.configure(label_background = self['selectbackground']) + self._labelWidget.configure(label_foreground = self['selectforeground']) + #self._viewButton.configure(background = self._selectbg) + cmd = self['selectcommand'] + if callable(cmd): + cmd(self) + + def _unhighlight(self): + #self._subHull.configure(background = self._bg, relief = 'flat') + if self['label'] != None: + self._labelWidget.configure(label_background = self['background']) + self._labelWidget.configure(label_foreground = self['foreground']) + #self._viewButton.configure(background = self._bg) + cmd = self['deselectcommand'] + if callable(cmd): + cmd(self) + + def _setlast(self, last): + self._last = last + + cw = int(self._lineCanvas['width']) + ch = int(self._lineCanvas['height']) + + if last: + self._lineCanvas.create_line(cw/2, 0, cw/2, ch/2, tag='vline') + else: + self._lineCanvas.create_line(cw/2, 0, cw/2, ch, tag='vline') + + +class _BranchNode(_LeafNode, _Branching): #Pmw.MegaWidget): + + def __init__(self, parent, nodeName, treeRoot, parentnode, last = 1, **kw): + # Define the megawidget options. + INITOPT = Pmw.INITOPT + optiondefs = ( + ('view', 'collapsed', None), + ('expandcommand', None, None), + ('collapsecommand', None, None), + ('indent', 0, INITOPT) + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + apply(_LeafNode.__init__, + (self, parent, nodeName, treeRoot, parentnode, last), + kw) + _Branching.__init__(self) + + # Create the components + interior = self._hull + + # Create the expand/collapse button + self._viewButton = self.createcomponent('viewbutton', (), None, + Tkinter.Canvas, + (interior,), + background = self['background'], + width = self._labelheight - 4, + height = self._labelheight - 4, + borderwidth = 2, + relief = 'raised') + + self._viewButton.grid(column = 0, row = 0, sticky='se') + self._viewButton.bind('', self._showbuttonpress) + self._viewButton.bind('', self._toggleview) + + # The label widget is already created by the base class, however + # we do need to make some slight modifications. + if self['label'] != None: + self._labelWidget.component('label').bind('', + self._toggleview) + self._labelWidget.grid(column=1, row=0, columnspan = 3, sticky='sw') + + # A line canvas is already created for us, we just need to make + # some slight modifications + self._lineCanvas.delete('hline') + self._lineCanvas.grid_forget() + + + # Set the minsize of column 1 to control additional branch frame indentation + self.grid_columnconfigure(1, minsize = self['indent']) + + # Create the branch frame that will contain all the branch/leaf nodes + self._branchFrame = self.createcomponent('frame', (), None, + Tkinter.Frame, (interior,), + #borderwidth=2, + #relief='ridge', + ) + self.grid_columnconfigure(2,minsize=0, weight=1) + #self.grid_rowconfigure(0,minsize=0) + + if(self['view'] == 'expanded'): + Pmw.drawarrow(self._viewButton, + self['foreground'], + 'down', 'arrow') + self._branchFrame.grid(column = 2, row = 1, sticky='nw') + if not self._last: + self._branchFrame.update() + bh = self._branchFrame.winfo_height() + self._lineCanvas.configure(height = bh) + self._lineCanvas.grid(column = 0, row = 1, sticky='news') + cw = int(self._lineCanvas['width']) + ch = int(self._lineCanvas['height']) + #self._lineCanvas.create_line(cw/2, 1, cw/2, ch, tag = 'vline') + self._lineCanvas.coords('vline', cw/2, 1, cw/2, ch) + else: + Pmw.drawarrow(self._viewButton, + self['foreground'], + 'right', 'arrow') + self._viewButton.configure(relief = 'raised') + + + # Check keywords and initialise options. + self.initialiseoptions() + + + + def _showbuttonpress(self, event): + self._viewButton.configure(relief = 'sunken') + + def _toggleview(self, event): + self._viewButton.configure(relief = 'sunken') + self.select() + if(self['view'] == 'expanded'): + self.collapsetree() + else: + self.expandtree() + self._viewButton.configure(relief = 'raised') + + def expandtree(self): + if(self['view'] == 'collapsed'): + cmd = self['expandcommand'] + if cmd is not None: + cmd(self) + self['view'] = 'expanded' + Pmw.drawarrow(self._viewButton, + self['foreground'], + 'down', 'arrow') + self._branchFrame.grid(column = 2, row = 1, sticky='nw') + + if not self._last: + self._branchFrame.update() + bh = self._branchFrame.winfo_height() + self._lineCanvas.configure(height = bh) + self._lineCanvas.grid(column = 0, row = 1, sticky='news') + cw = int(self._lineCanvas['width']) + ch = int(self._lineCanvas['height']) + #self._lineCanvas.create_line( cw/2, 1, cw/2, ch, tag = 'vline') + self._lineCanvas.coords('vline', cw/2, 1, cw/2, ch) + self._parentNode._sizechange() + + def collapsetree(self): + if(self['view'] == 'expanded'): + cmd = self['collapsecommand'] + if cmd is not None: + cmd(self) + self['view'] = 'collapsed' + Pmw.drawarrow(self._viewButton, + self['foreground'], + 'right', 'arrow') + self._branchFrame.grid_forget() + if not self._last: + #self._lineCanvas.delete('vline') + self._lineCanvas.grid_forget() + self._parentNode._sizechange() + + def _setlast(self, last): + self._last = last + if self['view'] == 'expanded': + self._branchFrame.update() + bh = self._branchFrame.winfo_height() + self._lineCanvas.configure(height = bh) + cw = int(self._lineCanvas['width']) + ch = int(self._lineCanvas['height']) + self._lineCanvas.delete('vline') + if not last: + self._lineCanvas.create_line(cw/2, 1, cw/2, ch, tag='vline') + + + def _sizechange(self): + if not self._last and self['view'] == 'expanded': + self._branchFrame.update() + bh = self._branchFrame.winfo_height() + self._lineCanvas.configure(height = bh) + if self._lineCanvas.coords('vline')[3] < bh: + cw = int(self._lineCanvas['width']) + ch = int(self._lineCanvas['height']) + #self._lineCanvas.delete('vline') + #self._lineCanvas.create_line(cw/2, 1, cw/2, ch, tag='vline') + self._lineCanvas.coords('vline', cw/2, 1, cw/2, ch) + self._parentNode._sizechange() + +class TreeBrowser(Pmw.MegaWidget, _Branching): + + def __init__(self, parent = None, nodeName = '0', **kw): + colors = Pmw.Color.getdefaultpalette(parent) + + # Define the megawidget options. + INITOPT = Pmw.INITOPT + optiondefs = ( + ('indent', 0, INITOPT), + ('selectbackground', colors['selectBackground'], INITOPT), + ('selectforeground', colors['selectForeground'], INITOPT), + ('background', colors['background'], INITOPT), + ('foreground', colors['foreground'], INITOPT), + #('selectrelief', 'raised', INITOPT), + ) + + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaWidget.__init__(self, parent) + _Branching.__init__(self) + + + # Create the components + interior = self._hull + + browserFrame = self.createcomponent('frame', (), None, + Pmw.ScrolledFrame, + (interior,), + ) + + browserFrame.pack(expand = 1, fill='both') + + self._branchFrame = browserFrame.interior() + + self._highlightedNode = None + self._treeRoot = self + self._nodeName = nodeName + # Check keywords and initialise options. + self.initialiseoptions() + + def _highlightnode(self, newNode): + if self._highlightedNode != newNode: + if self._highlightedNode != None: + self._highlightedNode._unhighlight() + self._highlightedNode = newNode + + def _unhighlightnode(self): + if self._highlightedNode != None: + self._highlightedNode._unhighlight() + self._highlightedNode = None + + def curselection(self): + retVal = None + if self._highlightedNode != None: + retVal = (self._highlightedNode, + self._highlightedNode._nodeName, + self._highlightedNode['label']) + return retVal + + def getname(self): + return self._nodeName + + # The top-level TreeBrowser widget only shows nodes in an expanded view + # but still provides collapsetree() and expandtree() methods so that users + # don't have to special case the top-level node + + def collapsetree(self): + return + + def expandtree(self): + return + + def _sizechange(self): + return + +if __name__ == '__main__': + + rootWin = Tkinter.Tk() + + Pmw.initialise() + + rootWin.title('TreeBrowser Demo') + + # Create the hierarchical tree browser widget + treeBrowser = TreeBrowser(rootWin, + #selectbackground = "darkgreen", + #selectforeground = 'lightgreen', + #background = 'green', + #indent = 10, + ) + + + def printselected(node): + selection = treeBrowser.curselection() + if selection != None: + print "Selected node name:", selection[1], " label:", selection[2] + + + def printdeselected(node): + selection = treeBrowser.curselection() + if selection != None: + print "Deselected node name:", selection[1], " label:", selection[2] + + def printexpanded(node): + print "Expanded node name:", node.getname(), " label:", node.getlabel() + + def printcollapsed(node): + print "Collapsed node name:", node.getname(), " label:", node.getlabel() + + + + for i in range(3): + # Add a tree node to the top level + treeNodeLevel1 = treeBrowser.addbranch(label = 'TreeNode %d'%i, + selectcommand = printselected, + deselectcommand = printdeselected, + expandcommand = printexpanded, + collapsecommand = printcollapsed, + ) + for j in range(3): + # Add a tree node to the second level + treeNodeLevel2 = treeNodeLevel1.addbranch(label = 'TreeNode %d.%d'%(i,j), + #selectforeground = 'yellow', + selectcommand = printselected, + deselectcommand = printdeselected, + expandcommand = printexpanded, + collapsecommand = printcollapsed, + ) + if i == 0 and j == 1: + dynamicTreeRootNode = treeNodeLevel1 + dynamicTreePosNode = treeNodeLevel2 + + for item in range((i+1)*(j+1)): + # Add a leaf node to the third level + leaf = treeNodeLevel2.addleaf(label = "Item %c"%(item+65), + #selectbackground = 'blue', + selectcommand = printselected, + deselectcommand = printdeselected) + for item in range(i+1): + # Add a leaf node to the top level + leaf = treeNodeLevel1.addleaf(label = "Item %c"%(item+65), + selectcommand = printselected, + deselectcommand = printdeselected) + + + treeNodeLevel1 = treeBrowser.addbranch(label = 'Check Button Label', + selectcommand = printselected, + deselectcommand = printdeselected, + expandcommand = printexpanded, + collapsecommand = printcollapsed, + ) + checkButton = Tkinter.Checkbutton(treeNodeLevel1.interior(), + text = 'Da Check Button', + relief = 'ridge', + command = treeNodeLevel1.select) + checkButton.pack() + + treeNodeLevel1.addleaf(label = 'Labeled Leaf', + selectcommand = printselected, + deselectcommand = printdeselected) + leaf = treeNodeLevel1.addleaf(label = 'Labeled Leaf w/ Checkbutton', + selectcommand = printselected, + deselectcommand = printdeselected) + checkButton = Tkinter.Checkbutton(leaf.interior(), + text = 'Da Check Button', + relief = 'ridge', + command = leaf.select) + checkButton.pack() + + + treeNodeLevel1 = treeBrowser.addbranch(selectcommand = printselected, + deselectcommand = printdeselected, + expandcommand = printexpanded, + collapsecommand = printcollapsed, + ) + checkButton = Tkinter.Checkbutton(treeNodeLevel1.interior(), + text = 'Check Button with no label', + relief = 'ridge', + command = treeNodeLevel1.select) + checkButton.pack() + + treeNodeLevel1 = treeBrowser.addbranch(label = 'Label', + selectcommand = printselected, + deselectcommand = printdeselected, + expandcommand = printexpanded, + collapsecommand = printcollapsed, + ) + + # setup dynamic tree node insertion and removal + class dynTree: + def __init__(self): + self.dyn = Tkinter.IntVar() + self.dtree = None + + self.dLeaf = treeBrowser.addleaf(selectcommand = self.dynSelected, + deselectcommand = self.dynDeselected) + + self.dCheckButton = Tkinter.Checkbutton(self.dLeaf.interior(), + text = 'Enable Dynamic Tree', + variable = self.dyn, + command = self.ChkBtnHandler) + self.dCheckButton.pack() + + + def dynSelected(self, node): + self.dCheckButton.configure(background = self.dLeaf.configure('selectbackground')[4]) + printselected(node) + + def dynDeselected(self, node): + self.dCheckButton.configure(background = self.dLeaf.configure('background')[4]) + printdeselected(node) + + def ChkBtnHandler(self): + self.dLeaf.select() + if self.dyn.get() == 1: + self.dtree = dynamicTreeRootNode.insertbranch(label = 'Dynamic Tree Node', + selectcommand = printselected, + deselectcommand = printdeselected, + expandcommand = printexpanded, + collapsecommand = printcollapsed, + before = dynamicTreePosNode) + self.dtree.addleaf(label = 'Dynamic Leaf 1', + selectcommand = printselected, + deselectcommand = printdeselected) + self.dtree.addleaf(label = 'Dynamic Leaf 2', + selectcommand = printselected, + deselectcommand = printdeselected) + else: + if self.dtree != None: + dynamicTreeRootNode.delete(self.dtree) + self.dtree = None + + + foo = dynTree() + + + treeBrowser.pack(expand = 1, fill='both') + + exitButton = Tkinter.Button(rootWin, text="Quit", command=rootWin.quit) + exitButton.pack() + + rootWin.mainloop() diff --git a/Pmw/Pmw_1_2/demos/AboutDialog.py b/Pmw/Pmw_1_2/demos/AboutDialog.py new file mode 100644 index 00000000..1760befe --- /dev/null +++ b/Pmw/Pmw_1_2/demos/AboutDialog.py @@ -0,0 +1,43 @@ +title = 'Pmw.AboutDialog demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create dialog. + Pmw.aboutversion('9.9') + Pmw.aboutcopyright('Copyright My Company 1999\nAll rights reserved') + Pmw.aboutcontact( + 'For information about this application contact:\n' + + ' My Help Desk\n' + + ' Phone: +61 2 9876 5432\n' + + ' email: help@my.company.com.au' + ) + self.about = Pmw.AboutDialog(parent, applicationname = 'My Application') + self.about.withdraw() + + # Create button to launch the dialog. + w = Tkinter.Button(parent, text = 'Show about dialog', + command = self.execute) + w.pack(padx = 8, pady = 8) + + def execute(self): + self.about.show() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/All.py b/Pmw/Pmw_1_2/demos/All.py new file mode 100755 index 00000000..f94955cf --- /dev/null +++ b/Pmw/Pmw_1_2/demos/All.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python + +# ------------------------------------------------------------------ +# Display a splash screen as quickly as possible (before importing +# modules and initialising Pmw). + +import Tkinter +root = Tkinter.Tk(className = 'Demo') +root.withdraw() + +splash = Tkinter.Toplevel() +splash.withdraw() +splash.title('Welcome to the Pmw demos') +text = Tkinter.Label(splash, + font=('Helvetica', 16, 'bold'), + relief = 'raised', + borderwidth = 2, + padx=50, pady=50, + text = + 'Welcome to the Pmw megawidgets demo.\n' + '\n' + 'In a moment the main window will appear.\n' + 'Please enjoy yourself while you wait.\n' + 'You may be interested to know that splash screens\n' + '(as this window is called) were first devised to draw\n' + 'attention away from the fact the certain applications\n' + 'are slow to start. They are normally flashier and more\n' + 'entertaining than this one. This is a budget model.' +) +text.pack(fill = 'both', expand = 1) +splash.update_idletasks() + +width = splash.winfo_reqwidth() +height = splash.winfo_reqheight() +x = (root.winfo_screenwidth() - width) / 2 - root.winfo_vrootx() +y = (root.winfo_screenheight() - height) / 3 - root.winfo_vrooty() +if x < 0: + x = 0 +if y < 0: + y = 0 +geometry = '%dx%d+%d+%d' % (width, height, x, y) + +splash.geometry(geometry) +splash.update_idletasks() +splash.deiconify() +root.update() + +# ------------------------------------------------------------------ + +# Now crank up the application windows. + +import imp +import os +import re +import string +import sys +import types +import Tkinter +import DemoVersion +import Args + +# Find where the other scripts are, so they can be listed. +if __name__ == '__main__': + script_name = sys.argv[0] +else: + script_name = imp.find_module('DemoVersion')[1] + +script_name = os.path.normpath(script_name) +script_name = DemoVersion.expandLinks(script_name) +script_dir = os.path.dirname(script_name) +script_dir = DemoVersion.expandLinks(script_dir) + +# Add the '../../..' directory to the path. +package_dir = os.path.dirname(script_dir) +package_dir = DemoVersion.expandLinks(package_dir) +package_dir = os.path.dirname(package_dir) +package_dir = DemoVersion.expandLinks(package_dir) +package_dir = os.path.dirname(package_dir) +package_dir = DemoVersion.expandLinks(package_dir) +sys.path[:0] = [package_dir] + +# Import Pmw after modifying sys.path (it may not be in the default path). +import Pmw +DemoVersion.setPmwVersion() + +class Demo(Pmw.MegaWidget): + + def __init__(self, parent=None, **kw): + + # Define the megawidget options. + optiondefs = () + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaWidget.__init__(self, parent) + + # Create the contents. + top = self.interior() + + panes = Pmw.PanedWidget(top, orient = 'horizontal') + panes.pack(fill = 'both', expand = 1) + + panes.add('widgetlist') + self._widgetlist = Pmw.ScrolledListBox(panes.pane('widgetlist'), + selectioncommand = Pmw.busycallback(self.startDemo), + label_text = 'Select a widget:', + labelpos = 'nw', + vscrollmode = 'dynamic', + hscrollmode = 'none', + listbox_exportselection = 0) + self._widgetlist.pack(fill = 'both', expand = 1, padx = 8) + + panes.add('info') + self._status = Tkinter.Label(panes.pane('info')) + self._status.pack(padx = 8, anchor = 'w') + + self._example = Tkinter.Frame(panes.pane('info'), + borderwidth = 2, + relief = 'sunken', + background = 'white') + self._example.pack(fill = 'both', expand = 1, padx = 8) + + self.buttonBox = Pmw.ButtonBox(top) + self.buttonBox.pack(fill = 'x') + + # Add the buttons and make them all the same width. + self._traceText = 'Trace tk calls' + self._stopTraceText = 'Stop trace' + self.buttonBox.add('Trace', text = self._traceText, + command = self.trace) + self.buttonBox.add('Code', text = 'Show code', command = self.showCode) + self.buttonBox.add('Exit', text = 'Exit', command = sys.exit) + self.buttonBox.alignbuttons() + + # Create the window to display the python code. + self.codeWindow = Pmw.TextDialog(parent, + title = 'Python source', + buttons = ('Dismiss',), + scrolledtext_labelpos = 'n', + label_text = 'Source') + self.codeWindow.withdraw() + self.codeWindow.insert('end', '') + + self.demoName = None + self._loadDemos() + + # Check keywords and initialise options. + self.initialiseoptions() + + def startDemo(self): + # Import the selected module and create and instance of the module's + # Demo class. + + sels = self._widgetlist.getcurselection() + if len(sels) == 0: + print 'No demonstrations to display' + return + demoName = sels[0] + + # Ignore if this if it is a sub title. + if demoName[0] != ' ': + self._widgetlist.bell() + return + + # Strip the leading two spaces. + demoName = demoName[2:] + + # Ignore if this demo is already being shown. + if self.demoName == demoName: + return + + self.demoName = demoName + + self.showStatus('Loading ' + demoName) + # Busy cursor + self.update_idletasks() + + for window in self._example.winfo_children(): + window.destroy() + + frame = Tkinter.Frame(self._example) + frame.pack(expand = 1) + exec 'import ' + demoName + # Need to keep a reference to the widget, so that variables, etc + # are not deleted. + self.widget = eval(demoName + '.Demo(frame)') + title = eval(demoName + '.title') + self.showStatus(title) + + if self.codeWindow.state() == 'normal': + self.insertCode() + + def showStatus(self, text): + self._status.configure(text = text) + + def showCode(self): + if self.codeWindow.state() != 'normal': + if self.demoName is None: + print 'No demonstration selected' + return + self.insertCode() + + self.codeWindow.show() + + def insertCode(self): + self.codeWindow.clear() + fileName = os.path.join(script_dir, self.demoName + '.py') + self.codeWindow.importfile(fileName) + self.codeWindow.configure(label_text = self.demoName + ' source') + + def trace(self): + text = self.buttonBox.component('Trace').cget('text') + if text == self._traceText: + self.buttonBox.configure(Trace_text = self._stopTraceText) + Pmw.tracetk(root, 1) + self.showStatus('Trace will appear on standard output') + else: + self.buttonBox.configure(Trace_text = self._traceText) + Pmw.tracetk(root, 0) + self.showStatus('Tk call tracing stopped') + + def _loadDemos(self): + files = os.listdir(script_dir) + files.sort() + megawidgets = [] + others = [] + for file in files: + if re.search('.py$', file) is not None and \ + file not in ['All.py', 'DemoVersion.py', 'Args.py']: + demoName = file[:-3] + index = string.find(demoName, '_') + if index < 0: + testattr = demoName + else: + testattr = demoName[:index] + if hasattr(Pmw, testattr): + megawidgets.append(demoName) + else: + others.append(demoName) + + self._widgetlist.insert('end', 'Megawidget demos:') + for name in megawidgets: + self._widgetlist.insert('end', ' ' + name) + self._widgetlist.insert('end', 'Other demos:') + for name in others: + self._widgetlist.insert('end', ' ' + name) + self._widgetlist.select_set(1) + +class StdOut: + def __init__(self, displayCommand): + self.displayCommand = displayCommand + self.text = '\n' + + def write(self, text): + if self.text[-1] == '\n': + self.text = text + else: + self.text = self.text + text + if self.text[-1] == '\n': + text = self.text[:-1] + else: + text = self.text + self.displayCommand(text) + +if os.name == 'nt': + defaultFontSize = 16 +else: + defaultFontSize = 12 + +commandLineArgSpecs = ( + ('fontscheme', 0, 'scheme', 'fonts to use [eg pmw2] (Tk defaults)'), + ('fontsize', 0, 'num', 'size of fonts to use with fontscheme', defaultFontSize), + ('stdout', 0, Args.Bool, 'print messages rather than display in label'), +) + +program = 'All.py' +msg = Args.parseArgs(program, sys.argv, commandLineArgSpecs, 0) +if msg is not None: + print msg + sys.exit() + +size = Args.get('fontsize') +fontScheme = Args.get('fontscheme') +Pmw.initialise(root, size = size, fontScheme = fontScheme, useTkOptionDb = 1) + +root.title('Pmw ' + Pmw.version() + ' megawidget demonstration') +if size < 18: + geometry = '800x550' +else: + geometry = '1000x700' +root.geometry(geometry) + +demo = Demo(root) +demo.pack(fill = 'both', expand = 1) +demo.focus() + +# Redirect standard output from demos to status line (unless -stdout +# option given on command line). +if not Args.get('stdout'): + sys.stdout = StdOut(demo.showStatus) + +# Start the first demo. +demo.startDemo() + +# Get rid of the splash screen +root.deiconify() +root.update() +splash.destroy() + +root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/Args.py b/Pmw/Pmw_1_2/demos/Args.py new file mode 100644 index 00000000..1bbedf91 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Args.py @@ -0,0 +1,191 @@ +"""Handle command line arguments. + +This module contains functions to parse and access the arguments given +to the program on the command line. +""" + +import types +import string +import sys + +# Symbolic constants for the indexes into an argument specifier tuple. +NAME = 0 +MANDATORY = 1 +TYPE = 2 +HELP = 3 +DEFAULT = 4 +SPEC_LENGTH = 5 + +Bool = [] + +helpSpec = ( + ('help', 0, Bool, 'print help and exit'), +) + +def parseArgs(title, argv, argSpecs, filesOK): + """Parse and check command line arguments. + + Scan the command line arguments in *argv* according to the argument + specifier *argSpecs*. Return **None** if there are no errors in + the arguments, otherwise return an error string describing the error. + + This function must be called to initialise this module. + + title -- The name of the program. This is used when returning + error messages or help text. + + argv -- A sequence containing the arguments given to the program. + Normally **sys.argv**. + + argSpecs -- A sequence of argument specifiers. Each specifier describes + a valid command line argument and consists of 4 or 5 items: + + - The argument name (without a leading minus sign **-**). + + - A boolean value, true if the argument is mandatory. + + - This should be **Args.Bool** if the argument has no option. + Otherwise it should be a string describing the option + required for this argument. This is used when printing help. + + - A short string describing the argument. + + - The default value of the argument. This should only be used + for non-mandatory arguments expecting an option. + + For example: + ( + ('foreground', 0, 'colour', 'colour of text', 'black'), + ('geometry', 0, 'spec', 'geometry of initial window'), + ('server', 1, 'ompserver', 'ompserver to connect to'), + ('silent', 0, Args.Bool, 'do not sound bell'), + ) + """ + + global programName + global _fileList + + errMsg = title + ' command line error: ' + programName = argv[0]; + + argSpecs = helpSpec + argSpecs + argSpecDic = {} + for spec in argSpecs: + arg = spec[NAME] + argSpecDic[arg] = spec + if len(spec) >= SPEC_LENGTH: + set(arg, spec[DEFAULT]) + elif spec[TYPE] is Bool: + set(arg, 0) + else: + set(arg, None) + + knownKeys = argSpecDic.keys() + + i = 1 + _fileList = [] + argc = len(argv) + while i < argc: + arg = argv[i] + key = arg[1:] + if key in knownKeys: + spec = argSpecDic[key] + if spec[TYPE] is Bool: + set(key, 1) + else: + i = i + 1 + if i >= argc: + return errMsg + 'missing argument to \'' + arg + '\' option.' + value = argv[i] + if len(spec) >= SPEC_LENGTH: + try: + if type(spec[DEFAULT]) == types.IntType: + typeStr = 'integer' + value = string.atoi(value) + elif type(spec[DEFAULT]) == types.FloatType: + typeStr = 'float' + value = string.atof(value) + except: + sys.exc_traceback = None # Clean up object references + return errMsg + 'cannot convert string \'' + value + \ + '\' to ' + typeStr + ' for option \'-' + key + '\'.' + set(key, value) + else: + _fileList.append(arg) + i = i + 1 + + if get('help'): + return _helpString(title, argSpecs) + + if not filesOK and len(_fileList) > 0: + if len(_fileList) == 1: + return errMsg + 'unknown option \'' + str(_fileList[0]) + '\'.' + else: + return errMsg + 'unknown options ' + str(_fileList) + '.' + + + _missing = [] + for spec in argSpecs: + if spec[MANDATORY] and get(spec[NAME]) is None: + _missing.append(spec[NAME]) + if len(_missing) == 1: + return errMsg + 'required argument \'-' + \ + str(_missing[0]) + '\' is missing.' + elif len(_missing) > 1: + return errMsg + 'required arguments ' + \ + str(map(lambda s: '-' + s, _missing)) + ' are missing.' + + return None + +def fileList(): + return _fileList + +def _helpString(title, argSpecs): + max = 0 + for spec in argSpecs: + if spec[TYPE] is Bool: + width = len(spec[NAME]) + 1 + else: + width = len(spec[NAME]) + 4 + len(spec[TYPE]) + if width > max: + max = width + + rtn = title + ' command line arguments:' + format = '\n %-' + str(max) + 's %s' + for mandatory in (1, 0): + needHeader = 1 + for spec in argSpecs: + if mandatory and spec[MANDATORY] or not mandatory and not spec[MANDATORY]: + if needHeader: + if mandatory: + rtn = rtn + '\n Mandatory arguments:' + else: + rtn = rtn + '\n Optional arguments (defaults in parentheses):' + needHeader = 0 + if spec[TYPE] is Bool: + arg = '-%s' % spec[NAME] + else: + arg = '-%s <%s>' % (spec[NAME], spec[TYPE]) + if len(spec) >= SPEC_LENGTH: + if type(spec[DEFAULT]) == types.StringType: + definition = spec[HELP] + ' (' + spec[DEFAULT] + ')' + else: + definition = spec[HELP] + ' (' + str(spec[DEFAULT]) + ')' + else: + definition = spec[HELP] + rtn = rtn + format % (arg, definition) + + return rtn + +def exists(key): + return configDict.has_key(key) + +def get(key): + return configDict[key] + +def set(key, value): + global configDict + + configDict[key] = value + +configDict = {} diff --git a/Pmw/Pmw_1_2/demos/Balloon.py b/Pmw/Pmw_1_2/demos/Balloon.py new file mode 100644 index 00000000..71788f64 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Balloon.py @@ -0,0 +1,185 @@ +title = 'Pmw.Balloon demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the Balloon. + self.balloon = Pmw.Balloon(parent) + + # Create some widgets and megawidgets with balloon help. + frame = Tkinter.Frame(parent) + frame.pack(padx = 10, pady = 5) + field = Pmw.EntryField(frame, + labelpos = 'nw', + label_text = 'Command:') + field.setentry('mycommand -name foo') + field.pack(side = 'left', padx = 10) + self.balloon.bind(field, 'Command to\nstart/stop', + 'Enter the shell command to control') + + start = Tkinter.Button(frame, text='Start') + start.pack(side='left', padx = 10) + self.balloon.bind(start, 'Start the command') + + stop = Tkinter.Button(frame, text='Stop') + stop.pack(side='left', padx = 10) + self.balloon.bind(stop, 'Stop the command') + + self.suicide = Tkinter.Button(frame, text='Kill me soon!', + command = self.killButton) + self.suicide.pack(side='left', padx = 10) + self.balloon.bind(self.suicide, 'Watch this button disappear!') + + scrolledCanvas = Pmw.ScrolledCanvas(parent, + canvas_width = 300, + canvas_height = 115, + ) + scrolledCanvas.pack() + canvas = scrolledCanvas.component('canvas') + self.canvas = canvas + + # Create some canvas items and individual help. + item = canvas.create_arc(5, 5, 35, 35, fill = 'red', extent = 315) + self.balloon.tagbind(canvas, item, 'This is help for\nan arc item') + item = canvas.create_bitmap(20, 150, bitmap = 'question') + self.balloon.tagbind(canvas, item, 'This is help for\na bitmap') + item = canvas.create_line(50, 60, 70, 80, 85, 20, width = 5) + self.balloon.tagbind(canvas, item, 'This is help for\na line item') + item = canvas.create_text(10, 90, text = 'Canvas items with balloons', + anchor = 'nw', font = field.cget('entry_font')) + self.balloon.tagbind(canvas, item, 'This is help for\na text item') + + # Create two canvas items which have the same tag and which use + # the same help. + canvas.create_rectangle(100, 10, 170, 50, fill = 'aliceblue', + tags = 'TAG1') + self.bluecircle = canvas.create_oval(110, 30, 160, 80, fill = 'blue', + tags = 'TAG1') + self.balloon.tagbind(canvas, 'TAG1', + 'This is help for the two blue items' + '\n' * 10 + + 'It is very, very big.', + 'This is help for the two blue items') + item = canvas.create_text(180, 10, text = 'Delete', + anchor = 'nw', font = field.cget('entry_font')) + self.balloon.tagbind(canvas, item, + 'After 2 seconds,\ndelete the blue circle') + canvas.tag_bind(item, '', self._canvasButtonpress) + scrolledCanvas.resizescrollregion() + + scrolledText = Pmw.ScrolledText(parent, + text_width = 32, + text_height = 4, + text_wrap = 'none', + ) + scrolledText.pack(pady = 5) + text = scrolledText.component('text') + self.text = text + + text.insert('end', + 'This is a text widget with ', '', + ' balloon', 'TAG1', + '\nhelp. Find the ', '', + ' text ', 'TAG1', + ' tagged with', '', + ' help.', 'TAG2', + '\n', '', + 'Remove tag 1.', 'TAG3', + '\nAnother line.\nAnd another', '', + ) + text.tag_configure('TAG1', borderwidth = 2, relief = 'sunken') + text.tag_configure('TAG3', borderwidth = 2, relief = 'raised') + + self.balloon.tagbind(text, 'TAG1', + 'There is one secret\nballoon help.\nCan you find it?') + self.balloon.tagbind(text, 'TAG2', + 'Well done!\nYou found it!') + self.balloon.tagbind(text, 'TAG3', + 'After 2 seconds\ndelete the tag') + text.tag_bind('TAG3', '', self._textButtonpress) + + frame = Tkinter.Frame(parent) + frame.pack(padx = 10) + self.toggleBalloonVar = Tkinter.IntVar() + self.toggleBalloonVar.set(1) + toggle = Tkinter.Checkbutton(frame, + variable = self.toggleBalloonVar, + text = 'Balloon help', command = self.toggle) + toggle.pack(side = 'left', padx = 10) + self.balloon.bind(toggle, 'Toggle balloon help\non and off') + + self.toggleStatusVar = Tkinter.IntVar() + self.toggleStatusVar.set(1) + toggle = Tkinter.Checkbutton(frame, + variable = self.toggleStatusVar, + text = 'Status help', command = self.toggle) + toggle.pack(side = 'left', padx = 10) + self.balloon.bind(toggle, + 'Toggle status help on and off, on and off' + '\n' * 10 + + 'It is very, very big, too.', + 'Toggle status help on and off') + + # Create and pack the MessageBar. + messageBar = Pmw.MessageBar(parent, + entry_width = 40, + entry_relief='groove', + labelpos = 'w', + label_text = 'Status:') + messageBar.pack(fill = 'x', expand = 1, padx = 10, pady = 5) + + # Configure the balloon to display its status messages in the + # message bar. + self.balloon.configure(statuscommand = messageBar.helpmessage) + + def toggle(self): + if self.toggleBalloonVar.get(): + if self.toggleStatusVar.get(): + self.balloon.configure(state = 'both') + else: + self.balloon.configure(state = 'balloon') + else: + if self.toggleStatusVar.get(): + self.balloon.configure(state = 'status') + else: + self.balloon.configure(state = 'none') + + def killButton(self): + # Test for old bug when destroying widgets 1) while the + # balloon was up and 2) during the initwait period. + print 'Destroying button in 2 seconds' + self.suicide.after(2000, self.suicide.destroy) + + def _canvasButtonpress(self, event): + print 'Destroying blue circle in 2 seconds' + self.canvas.after(2000, self.deleteBlueCircle) + + def deleteBlueCircle(self): + self.balloon.tagunbind(self.canvas, self.bluecircle) + self.canvas.delete(self.bluecircle) + + def _textButtonpress(self, event): + print 'Deleting the text tag in 2 seconds' + self.text.after(2000, self.deleteTextTag) + + def deleteTextTag(self): + self.balloon.tagunbind(self.text, 'TAG1') + self.text.tag_delete('TAG1') + + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root, 12, fontScheme = 'default') + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/BltGraph.py b/Pmw/Pmw_1_2/demos/BltGraph.py new file mode 100644 index 00000000..a71c5c34 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/BltGraph.py @@ -0,0 +1,241 @@ +title = 'Blt Graph demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import Tkinter +import Pmw + +# Simple random number generator. +rand = 12345 +def random(): + global rand + rand = (rand * 125) % 2796203 + return rand + +class GraphDemo(Pmw.MegaToplevel): + + def __init__(self, parent=None, **kw): + + # Define the megawidget options. + optiondefs = ( + ('size', 10, Pmw.INITOPT), + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaToplevel.__init__(self, parent) + + # Create the graph. + self.createWidgets() + + # Check keywords and initialise options. + self.initialiseoptions() + + def createWidgets(self): + # Create vectors for use as x and y data points. + self._numElements = 7 + self._vectorSize = self['size'] + self._vector_x = Pmw.Blt.Vector() + self._vector_y = [] + for y in range(self._numElements): + self._vector_y.append(Pmw.Blt.Vector()) + for index in range(self._vectorSize): + self._vector_x.append(index) + for y in range(self._numElements): + self._vector_y[y].append(random() % 100) + + interior = self.interior() + + controlFrame = Tkinter.Frame(interior) + controlFrame.pack(side = 'bottom', fill = 'x', expand = 0) + + # Create an option menu for the kind of elements to create. + elementtype = Pmw.OptionMenu(controlFrame, + labelpos = 'nw', + label_text = 'Element type', + items = ['bars', 'lines', 'mixed', 'none'], + command = self._setelementtype, + menubutton_width = 8, + ) + elementtype.pack(side = 'left') + + # Create an option menu for the barmode option. + barmode = Pmw.OptionMenu(controlFrame, + labelpos = 'nw', + label_text = 'Bar mode', + items = ['normal', 'stacked', 'aligned', 'overlap'], + command = self._setbarmode, + menubutton_width = 8, + ) + barmode.pack(side = 'left') + + # Create an option menu for the smooth option. + self.smooth = Pmw.OptionMenu(controlFrame, + labelpos = 'nw', + label_text = 'Smooth', + items = ['linear', 'step', 'natural', 'quadratic'], + command = self._setsmooth, + menubutton_width = 9, + ) + self.smooth.pack(side = 'left') + + # Create an option menu to reverse sort the elements. + sortelements = Pmw.OptionMenu(controlFrame, + labelpos = 'nw', + label_text = 'Order', + items = ['normal', 'reverse'], + command = self._setsortelements, + menubutton_width = 8, + ) + sortelements.pack(side = 'left') + + # Create an option menu for the bufferelements option. + bufferelements = Pmw.OptionMenu(controlFrame, + labelpos = 'nw', + label_text = 'Buffering', + items = ['buffered', 'unbuffered'], + command = self._setbufferelements, + menubutton_width = 10, + ) + bufferelements.pack(side = 'left') + + # Create a button to add a point to the vector. + addpoint = Tkinter.Button(controlFrame, text = 'Add point', + command = Pmw.busycallback(self._addpoint)) + addpoint.pack(side = 'left', fill = 'x', expand = 0) + + # Create a button to close the window + close = Tkinter.Button(controlFrame, text = 'Close', + command = Pmw.busycallback(self.destroy)) + close.pack(side = 'left', fill = 'x', expand = 0) + + # Create the graph and its elements. + self._graph = Pmw.Blt.Graph(interior) + self._graph.pack(expand = 1, fill = 'both') + self._graph.yaxis_configure(command=self.yaxisCommand) + elementtype.invoke('mixed') + bufferelements.invoke('buffered') + + def yaxisCommand(self, graph, value): + try: + num = string.atoi(value) + return '%d %3d' % (num * 3, num) + except ValueError: + num = string.atof(value) + return '%g %3g' % (num * 3, num) + + def _setelementtype(self, type): + elements = self._graph.element_names() + apply(self._graph.element_delete, elements) + + if type == 'none': + return + + colorList = Pmw.Color.spectrum(self._numElements) + for elem in range(self._numElements): + if elem == 0: + hue = None + else: + hue = (elem + 1.0) / self._numElements * 6.28318 + foreground = colorList[elem] + background = Pmw.Color.changebrightness(self, foreground, 0.8) + if type == 'mixed': + if elem < self._numElements / 2: + bar = 0 + else: + bar = 1 + elif type == 'bars': + bar = 1 + else: + bar = 0 + if bar: + self._graph.bar_create( + 'var' + str(elem), + xdata=self._vector_x, + ydata=self._vector_y[elem], + foreground = foreground, + background = background) + else: + self._graph.line_create( + 'var' + str(elem), + linewidth = 4, + xdata=self._vector_x, + ydata=self._vector_y[elem], + smooth = self.smooth.getcurselection(), + color = foreground) + + def _setbarmode(self, tag): + self._graph.configure(barmode = tag) + + def _setsmooth(self, tag): + for element in self._graph.element_show(): + if self._graph.element_type(element) == 'line': + self._graph.element_configure(element, smooth = tag) + + def _setbufferelements(self, tag): + self._graph.configure(bufferelements = (tag == 'buffered')) + + def _setsortelements(self, tag): + element_list = list(self._graph.element_show()) + if len(element_list) > 1: + if (tag == 'normal') == (element_list[-1] != 'var0'): + element_list.reverse() + self._graph.element_show(element_list) + + def _addpoint(self): + self._vector_x.append(self._vectorSize) + for y in range(self._numElements): + self._vector_y[y].append(random() % 100) + self._vectorSize = self._vectorSize + 1 + +class Demo: + def __init__(self, parent): + if not Pmw.Blt.haveblt(parent): + message = 'Sorry\nThe BLT package has not been\n' + \ + 'installed on this system.\n' + \ + 'Please install it and try again.' + w = Tkinter.Label(parent, text = message) + w.pack(padx = 8, pady = 8) + return + + message = 'This is a simple demonstration of the\n' + \ + 'BLT graph widget.\n' + \ + 'Select the number of points to display and\n' + \ + 'click on the button to display the graph.' + w = Tkinter.Label(parent, text = message) + w.pack(padx = 8, pady = 8) + + # Create combobox to select number of points to display. + self.combo = Pmw.ComboBox(parent, + scrolledlist_items = ('10', '25', '50', '100', '300'), + entryfield_value = '10') + self.combo.pack(padx = 8, pady = 8) + + # Create button to start blt graph. + start = Tkinter.Button(parent, + text = 'Show BLT graph', + command = Pmw.busycallback(self.showGraphDemo)) + start.pack(padx = 8, pady = 8) + + self.parent = parent + + def showGraphDemo(self): + size = string.atoi(self.combo.get()) + demo = GraphDemo(self.parent, size = size) + demo.focus() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/BltTabset.py b/Pmw/Pmw_1_2/demos/BltTabset.py new file mode 100644 index 00000000..b6cf5894 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/BltTabset.py @@ -0,0 +1,101 @@ +title = 'Blt Tabset demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + if not Pmw.Blt.haveblt(parent): + message = 'Sorry\nThe BLT package has not been\n' + \ + 'installed on this system.\n' + \ + 'Please install it and try again.' + w = Tkinter.Label(parent, text = message) + w.pack(padx = 8, pady = 8) + return + + self.tabset = Pmw.Blt.Tabset(parent, + borderwidth = 0, + highlightthickness = 0, + selectpad = 0, + tiers = 2, + ) + background = self.tabset.cget('background') + self.tabset.configure(selectbackground = background, + tabbackground = background, activebackground = background) + + configurePanel = Tkinter.Frame(self.tabset) + sideMenu = Pmw.OptionMenu (configurePanel, + labelpos = 'w', + label_text = 'Side:', + items = ('top', 'bottom', 'left', 'right'), + menubutton_width = 10, + command = self.changeSide, + ) + sideMenu.pack(anchor = 'w', padx = 10, pady = 10) + + rotateMenu = Pmw.ComboBox(configurePanel, + labelpos = 'w', + label_text = 'Text rotation:', + entryfield_validate = 'integer', + entry_width = 8, + selectioncommand = self.rotateText, + scrolledlist_items = (0, 45, 90, 135, 180, 225, 270, 315), + ) + rotateMenu.pack(side = 'left', padx = 10, pady = 10) + + rotateMenu.selectitem(0) + self.rotateText('0') + + self.appearancePanel = Tkinter.Label(self.tabset) + helpersPanel = Tkinter.Button(self.tabset, + text = 'This is a lot\nof help!') + + self.tabset.insert('end', + 'Appearance', 'Configure', 'Helpers', 'Images') + + self.tabset.tab_configure('Appearance', + command = self.appearance_cb, fill = 'both') + self.tabset.tab_configure('Configure', window = configurePanel) + self.tabset.tab_configure('Images', + command = self.images_cb, fill = 'both') + self.tabset.tab_configure('Helpers', + window = helpersPanel, padx = 100, pady = 150) + + self.tabset.invoke(1) + self.tabset.pack(fill = 'both', expand = 1, padx = 5, pady = 5) + self.tabset.focus() + + def appearance_cb(self): + self.appearancePanel.configure( + text = 'Don\'t judge a book\nby it\'s cover.') + self.tabset.tab_configure('Appearance', window = self.appearancePanel) + + def images_cb(self): + self.appearancePanel.configure(text = 'Beauty is only\nskin deep.') + self.tabset.tab_configure('Images', window = self.appearancePanel) + + def changeSide(self, side): + self.tabset.configure(side = side) + + def rotateText(self, angle): + if Pmw.integervalidator(angle) == Pmw.OK: + self.tabset.configure(rotate = angle) + else: + self.tabset.bell() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ButtonBox.py b/Pmw/Pmw_1_2/demos/ButtonBox.py new file mode 100644 index 00000000..984ff36f --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ButtonBox.py @@ -0,0 +1,56 @@ +title = 'Pmw.ButtonBox demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack the ButtonBox. + self.buttonBox = Pmw.ButtonBox(parent, + labelpos = 'nw', + label_text = 'ButtonBox:', + frame_borderwidth = 2, + frame_relief = 'groove') + self.buttonBox.pack(fill = 'both', expand = 1, padx = 10, pady = 10) + + # Add some buttons to the ButtonBox. + self.buttonBox.add('OK', command = self.ok) + self.buttonBox.add('Apply', command = self.apply) + self.buttonBox.add('Cancel', command = self.cancel) + + # Set the default button (the one executed when is hit). + self.buttonBox.setdefault('OK') + parent.bind('', self._processReturnKey) + parent.focus_set() + + # Make all the buttons the same width. + self.buttonBox.alignbuttons() + + def _processReturnKey(self, event): + self.buttonBox.invoke() + + def ok(self): + print 'You clicked on OK' + + def apply(self): + print 'You clicked on Apply' + + def cancel(self): + print 'You clicked on Cancel' + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/Colors.py b/Pmw/Pmw_1_2/demos/Colors.py new file mode 100644 index 00000000..b6e0a5be --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Colors.py @@ -0,0 +1,50 @@ +title = 'Colorscheme demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + frame = Tkinter.Frame(parent) + frame.pack(fill = 'both', expand = 1) + + defaultPalette = Pmw.Color.getdefaultpalette(parent) + + colors = ('red', 'green', 'blue') + items = ('Testing', 'More testing', 'a test', 'foo', 'blah') + for count in range(len(colors)): + color = colors[count] + normalcolor = Pmw.Color.changebrightness(parent, color, 0.85) + Pmw.Color.setscheme(parent, normalcolor) + combo = Pmw.ComboBox(frame, + scrolledlist_items = items, + entryfield_value = items[0]) + combo.grid(sticky='nsew', row = count, column = 0) + + normalcolor = Pmw.Color.changebrightness(parent, color, 0.35) + Pmw.Color.setscheme(parent, normalcolor, foreground = 'white') + combo = Pmw.ComboBox(frame, + scrolledlist_items = items, + entryfield_value = items[0]) + combo.grid(sticky='nsew', row = count, column = 1) + + apply(Pmw.Color.setscheme, (parent,), defaultPalette) + #normalcolor = Pmw.Color.changebrightness(parent, 'red', 0.85) + #Pmw.Color.setscheme(parent, normalcolor) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ComboBox.py b/Pmw/Pmw_1_2/demos/ComboBox.py new file mode 100644 index 00000000..461fc809 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ComboBox.py @@ -0,0 +1,76 @@ +title = 'Pmw.ComboBox demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + parent.configure(background = 'white') + + # Create and pack the widget to be configured. + self.target = Tkinter.Label(parent, + relief = 'sunken', + padx = 20, + pady = 20, + ) + self.target.pack(fill = 'x', padx = 8, pady = 8) + + # Create and pack the simple ComboBox. + words = ('Monti', 'Python', 'ik', 'den', 'Holie', 'Grailen', '(Bok)') + simple = Pmw.ComboBox(parent, + label_text = 'Simple ComboBox:', + labelpos = 'nw', + selectioncommand = self.changeText, + scrolledlist_items = words, + dropdown = 0, + ) + simple.pack(side = 'left', fill = 'both', + expand = 1, padx = 8, pady = 8) + + # Display the first text. + first = words[0] + simple.selectitem(first) + self.changeText(first) + + # Create and pack the dropdown ComboBox. + colours = ('cornsilk1', 'snow1', 'seashell1', 'antiquewhite1', + 'bisque1', 'peachpuff1', 'navajowhite1', 'lemonchiffon1', + 'ivory1', 'honeydew1', 'lavenderblush1', 'mistyrose1') + dropdown = Pmw.ComboBox(parent, + label_text = 'Dropdown ComboBox:', + labelpos = 'nw', + selectioncommand = self.changeColour, + scrolledlist_items = colours, + ) + dropdown.pack(side = 'left', anchor = 'n', + fill = 'x', expand = 1, padx = 8, pady = 8) + + # Display the first colour. + first = colours[0] + dropdown.selectitem(first) + self.changeColour(first) + + def changeColour(self, colour): + print 'Colour: ' + colour + self.target.configure(background = colour) + + def changeText(self, text): + print 'Text: ' + text + self.target.configure(text = text) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ComboBoxDialog.py b/Pmw/Pmw_1_2/demos/ComboBoxDialog.py new file mode 100644 index 00000000..c0e3deda --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ComboBoxDialog.py @@ -0,0 +1,44 @@ +title = 'Pmw.ComboBoxDialog demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the dialog. + self.dialog = Pmw.ComboBoxDialog(parent, + title = 'My ComboBoxDialog', + buttons = ('OK', 'Cancel'), + defaultbutton = 'OK', + combobox_labelpos = 'n', + label_text = 'What do you think of Pmw?', + scrolledlist_items = ('Cool man', 'Cool', 'Good', 'Bad', 'Gross')) + self.dialog.withdraw() + + # Create button to launch the dialog. + w = Tkinter.Button(parent, + text = 'Show combo box dialog', + command = self.doit) + w.pack(padx = 8, pady = 8) + + def doit(self): + result = self.dialog.activate() + print 'You clicked on', result, self.dialog.get() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() + diff --git a/Pmw/Pmw_1_2/demos/ConfigClass.py b/Pmw/Pmw_1_2/demos/ConfigClass.py new file mode 100644 index 00000000..b4d2b7fd --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ConfigClass.py @@ -0,0 +1,76 @@ +title = 'Component python class configuration demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class MyButton(Tkinter.Button): + # This is just an ordinary button with special colors. + + def __init__(self, master=None, cnf={}, **kw): + self.__toggle = 0 + kw['background'] = 'green' + kw['activebackground'] = 'red' + apply(Tkinter.Button.__init__, (self, master, cnf), kw) + +class Demo: + def __init__(self, parent): + + # Create a title label: + label = Tkinter.Label(parent, + text = 'EntryFields with label components of specified type:') + label.pack(fill='x', expand=1, padx=10, pady=5) + + # Create and pack some EntryFields. + entries = [] + entry = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Label' + ) + entry.pack(fill='x', expand=1, padx=10, pady=5) + entries.append(entry) + + entry = Pmw.EntryField(parent, + labelpos = 'w', + label_pyclass = Tkinter.Button, + label_text = 'Button' + ) + entry.pack(fill='x', expand=1, padx=10, pady=5) + entries.append(entry) + + entry = Pmw.EntryField(parent, + labelpos = 'w', + label_pyclass = MyButton, + label_text = 'Special button' + ) + entry.pack(fill='x', expand=1, padx=10, pady=5) + entries.append(entry) + + Pmw.alignlabels(entries) + + # Create and pack a ButtonBox. + buttonBox = Pmw.ButtonBox(parent, + labelpos = 'nw', + label_text = 'ButtonBox:') + buttonBox.pack(fill = 'both', expand = 1, padx=10, pady=5) + + # Add some buttons to the ButtonBox. + buttonBox.add('with a') + buttonBox.add('special', pyclass = MyButton) + buttonBox.add('button') + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/Counter.py b/Pmw/Pmw_1_2/demos/Counter.py new file mode 100644 index 00000000..856b4dfa --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Counter.py @@ -0,0 +1,121 @@ +title = 'Pmw.Counter demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import time +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Need to use long ints here because on the Macintosh the maximum size + # of an integer is smaller than the value returned by time.time(). + now = (long(time.time()) / 300) * 300 + + # Create the Counters. + self._date = Pmw.Counter(parent, + labelpos = 'w', + label_text = 'Date (4-digit year):', + entryfield_value = + time.strftime('%d/%m/%Y', time.localtime(now)), + entryfield_command = self.execute, + entryfield_validate = {'validator' : 'date', 'format' : 'dmy'}, + datatype = {'counter' : 'date', 'format' : 'dmy', 'yyyy' : 1}) + + self._isodate = Pmw.Counter(parent, + labelpos = 'w', + label_text = 'ISO-Date (4-digit year):', + entryfield_value = + time.strftime('%Y-%m-%d', time.localtime(now)), + entryfield_command = self.execute, + entryfield_validate = {'validator' : 'date', 'format' : 'ymd', + 'separator' : '-' }, + datatype = {'counter' : 'date', 'format' : 'ymd', 'yyyy' : 1, + 'separator' : '-' }) + + self._time = Pmw.Counter(parent, + labelpos = 'w', + label_text = 'Time:', + entryfield_value = + time.strftime('%H:%M:%S', time.localtime(now)), + entryfield_validate = {'validator' : 'time', + 'min' : '00:00:00', 'max' : '23:59:59', + 'minstrict' : 0, 'maxstrict' : 0}, + datatype = {'counter' : 'time', 'time24' : 1}, + increment=5*60) + self._real = Pmw.Counter(parent, + labelpos = 'w', + label_text = 'Real (with comma)\nand extra\nlabel lines:', + label_justify = 'left', + entryfield_value = '1,5', + datatype = {'counter' : 'real', 'separator' : ','}, + entryfield_validate = {'validator' : 'real', + 'min' : '-2,0', 'max' : '5,0', + 'separator' : ','}, + increment = 0.1) + self._custom = Pmw.Counter(parent, + labelpos = 'w', + label_text = 'Custom:', + entryfield_value = specialword[:4], + datatype = _custom_counter, + entryfield_validate = _custom_validate) + self._int = Pmw.Counter(parent, + labelpos = 'w', + label_text = 'Vertical integer:', + orient = 'vertical', + entry_width = 2, + entryfield_value = 50, + entryfield_validate = {'validator' : 'integer', + 'min' : 0, 'max' : 99} + ) + + counters = (self._date, self._isodate, self._time, self._real, + self._custom) + Pmw.alignlabels(counters) + + # Pack them all. + for counter in counters: + counter.pack(fill='both', expand=1, padx=10, pady=5) + self._int.pack(padx=10, pady=5) + + def execute(self): + print 'Return pressed, value is', self._date.get() + +specialword = 'Monti Python ik den Holie Grailen (Bok)' + +def _custom_validate(text): + if string.find(specialword, text) == 0: + return 1 + else: + return -1 + +def _custom_counter(text, factor, increment): + # increment is ignored here. + if string.find(specialword, text) == 0: + length = len(text) + if factor == 1: + if length >= len(specialword): + raise ValueError, 'maximum length reached' + return specialword[:length + 1] + else: + if length == 0: + raise ValueError, 'empty string' + return specialword[:length - 1] + else: + raise ValueError, 'bad string ' + text + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/CounterDialog.py b/Pmw/Pmw_1_2/demos/CounterDialog.py new file mode 100644 index 00000000..808c3bf3 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/CounterDialog.py @@ -0,0 +1,60 @@ +title = 'Pmw.CounterDialog demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the dialog to prompt for the number of times to ring the bell. + self.dialog = Pmw.CounterDialog(parent, + label_text = 'Enter the number of times to\n' + \ + 'sound the bell (1 to 5)\n', + counter_labelpos = 'n', + entryfield_value = 2, + counter_datatype = 'numeric', + entryfield_validate = + {'validator' : 'numeric', 'min' : 1, 'max' : 5}, + buttons = ('OK', 'Cancel'), + defaultbutton = 'OK', + title = 'Bell ringing', + command = self.execute) + self.dialog.withdraw() + + # Create button to launch the dialog. + w = Tkinter.Button(parent, text = 'Show counter dialog', + command = self.dialog.activate) + w.pack(padx = 8, pady = 8) + + def execute(self, result): + if result is None or result == 'Cancel': + print 'Bell ringing cancelled' + self.dialog.deactivate() + else: + count = self.dialog.get() + if not self.dialog.valid(): + print 'Invalid entry: "' + count + '"' + else: + print 'Ringing the bell ' + count + ' times' + for num in range(string.atoi(count)): + if num != 0: + self.dialog.after(200) + self.dialog.bell() + self.dialog.deactivate() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/DemoVersion.py b/Pmw/Pmw_1_2/demos/DemoVersion.py new file mode 100644 index 00000000..477a9f95 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/DemoVersion.py @@ -0,0 +1,36 @@ +# Set the version of Pmw to use for the demonstrations based on the +# directory name. + +import imp +import os +import string + +def expandLinks(path): + if not os.path.isabs(path): + path = os.path.join(os.getcwd(), path) + while 1: + if not os.path.islink(path): + break + dir = os.path.dirname(path) + path = os.path.join(dir, os.readlink(path)) + + return path + +def setPmwVersion(): + file = imp.find_module(__name__)[1] + file = os.path.normpath(file) + file = expandLinks(file) + + dir = os.path.dirname(file) + dir = expandLinks(dir) + dir = os.path.dirname(dir) + dir = expandLinks(dir) + dir = os.path.basename(dir) + + version = string.replace(dir[4:], '_', '.') + import Pmw + if version in Pmw.installedversions(): + Pmw.setversion(version) + else: + print 'No such Pmw version', `version` + '.', + print 'Using default version', `Pmw.version()` diff --git a/Pmw/Pmw_1_2/demos/Dialog.py b/Pmw/Pmw_1_2/demos/Dialog.py new file mode 100644 index 00000000..3be3fdb0 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Dialog.py @@ -0,0 +1,89 @@ +title = 'Pmw.Dialog demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create two buttons to launch the dialog. + w = Tkinter.Button(parent, text = 'Show application modal dialog', + command = self.showAppModal) + w.pack(padx = 8, pady = 8) + + w = Tkinter.Button(parent, text = 'Show global modal dialog', + command = self.showGlobalModal) + w.pack(padx = 8, pady = 8) + + w = Tkinter.Button(parent, text = 'Show dialog with "no grab"', + command = self.showDialogNoGrab) + w.pack(padx = 8, pady = 8) + + w = Tkinter.Button(parent, text = + 'Show toplevel window which\n' + + 'will not get a busy cursor', + command = self.showExcludedWindow) + w.pack(padx = 8, pady = 8) + + # Create the dialog. + self.dialog = Pmw.Dialog(parent, + buttons = ('OK', 'Apply', 'Cancel', 'Help'), + defaultbutton = 'OK', + title = 'My dialog', + command = self.execute) + self.dialog.withdraw() + + # Add some contents to the dialog. + w = Tkinter.Label(self.dialog.interior(), + text = 'Pmw Dialog\n(put your widgets here)', + background = 'black', + foreground = 'white', + pady = 20) + w.pack(expand = 1, fill = 'both', padx = 4, pady = 4) + + # Create the window excluded from showbusycursor. + self.excluded = Pmw.MessageDialog(parent, + title = 'I still work', + message_text = + 'This window will not get\n' + + 'a busy cursor when modal dialogs\n' + + 'are activated. In addition,\n' + + 'you can still interact with\n' + + 'this window when a "no grab"\n' + + 'modal dialog is displayed.') + self.excluded.withdraw() + Pmw.setbusycursorattributes(self.excluded.component('hull'), + exclude = 1) + + def showAppModal(self): + self.dialog.activate(geometry = 'centerscreenalways') + + def showGlobalModal(self): + self.dialog.activate(globalMode = 1) + + def showDialogNoGrab(self): + self.dialog.activate(globalMode = 'nograb') + + def showExcludedWindow(self): + self.excluded.show() + + def execute(self, result): + print 'You clicked on', result + if result not in ('Apply', 'Help'): + self.dialog.deactivate(result) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/EntryField.py b/Pmw/Pmw_1_2/demos/EntryField.py new file mode 100644 index 00000000..69163816 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/EntryField.py @@ -0,0 +1,98 @@ +title = 'Pmw.EntryField demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import time +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack the EntryFields. + self._any = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Any:', + validate = None, + command = self.execute) + self._real = Pmw.EntryField(parent, + labelpos = 'w', + value = '55.5', + label_text = 'Real (10.0 to 99.0):', + validate = {'validator' : 'real', + 'min' : 10, 'max' : 99, 'minstrict' : 0}, + modifiedcommand = self.changed) + self._odd = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Odd length:', + validate = self.custom_validate, + value = 'ABC') + self._date = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Date (in 2000):', + value = '2000/2/29', + validate = {'validator' : 'date', + 'min' : '2000/1/1', 'max' : '2000/12/31', + 'minstrict' : 0, 'maxstrict' : 0, + 'format' : 'ymd'}, + ) + now = time.localtime(time.time()) + self._date2 = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Date (d.m.y):', + value = '%d.%d.%d' % (now[2], now[1], now[0]), + validate = {'validator' : 'date', + 'format' : 'dmy', 'separator' : '.'}, + ) + self._time = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Time (24hr clock):', + value = '8:00:00', + validate = {'validator' : 'time', + 'min' : '00:00:00', 'max' : '23:59:59', + 'minstrict' : 0, 'maxstrict' : 0}, + ) + self._comma = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Real (with comma):', + value = '123,456', + validate = {'validator' : 'real', 'separator' : ','}, + ) + + entries = (self._any, self._real, self._odd, self._date, self._date2, + self._time, self._comma) + + for entry in entries: + entry.pack(fill='x', expand=1, padx=10, pady=5) + Pmw.alignlabels(entries) + + self._any.component('entry').focus_set() + + def changed(self): + print 'Text changed, value is', self._real.getvalue() + + def execute(self): + print 'Return pressed, value is', self._any.getvalue() + + # This implements a custom validation routine. It simply checks + # if the string is of odd length. + def custom_validate(self, text): + print 'text:', text + if len(text) % 2 == 0: + return -1 + else: + return 1 + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ErrorHandling.py b/Pmw/Pmw_1_2/demos/ErrorHandling.py new file mode 100644 index 00000000..41fd10fc --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ErrorHandling.py @@ -0,0 +1,42 @@ +title = 'Pmw error handling demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create two buttons to generate errors. + w = Tkinter.Button(parent, text = 'Click here to generate\n' + + 'an error in a command callback.', command = self.execute) + w.pack(padx = 8, pady = 8) + + w = Tkinter.Button(parent, text = 'Click here to generate\n' + + 'an error in a callback called\nfrom an event binding.') + w.pack(padx = 8, pady = 8) + w.bind('', self.execute) + w.bind('', self.execute) + + def execute(self, event = None): + self._error() + + def _error(self): + # Divide by zero + 1/0 + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ExampleDemo.py b/Pmw/Pmw_1_2/demos/ExampleDemo.py new file mode 100644 index 00000000..f7ec1e71 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ExampleDemo.py @@ -0,0 +1,33 @@ +title = 'Pmw.EXAMPLE demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + + # Create and pack the EXAMPLEs. + self.widget1 = Pmw.Counter(parent) + self.widget1.setentry('1') + self.widget1.pack() + + self.widget2 = Pmw.Counter(parent, increment = 10) + self.widget2.setentry('100') + self.widget2.pack() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/Grid.py b/Pmw/Pmw_1_2/demos/Grid.py new file mode 100644 index 00000000..051863e5 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Grid.py @@ -0,0 +1,44 @@ +title = 'Grid geometry manager demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + frame = Tkinter.Frame(parent) + frame.pack(fill = 'both', expand = 1) + + button = {} + for num in range(0, 10): + button[num] = Tkinter.Button(frame, text = 'Button ' + str(num)) + + button[0].grid(column=0, row=0, rowspan=2, sticky='nsew') + button[1].grid(column=1, row=0, columnspan=3, sticky='nsew') + button[2].grid(column=1, row=1, rowspan=2, sticky='nsew') + button[3].grid(column=2, row=1) + button[4].grid(column=3, row=1) + button[5].grid(column=0, row=2) + button[6].grid(column=0, row=3, columnspan=2, sticky='nsew') + button[7].grid(column=2, row=2, columnspan=2, rowspan=2, sticky='nsew') + button[8].grid(column=0, row=4) + button[9].grid(column=3, row=4, sticky='e') + + frame.grid_rowconfigure(3, weight=1) + frame.grid_columnconfigure(3, weight=1) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/Group.py b/Pmw/Pmw_1_2/demos/Group.py new file mode 100644 index 00000000..b1c4ed5c --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Group.py @@ -0,0 +1,93 @@ +title = 'Pmw.Group demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + + # Create and pack the Groups. + w = Pmw.Group(parent, tag_text='label') + w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) + cw = Tkinter.Label(w.interior(), + text = 'A group with the\ndefault Label tag') + cw.pack(padx = 2, pady = 2, expand='yes', fill='both') + + w = Pmw.Group(parent, tag_pyclass = None) + w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) + cw = Tkinter.Label(w.interior(), text = 'A group\nwithout a tag') + cw.pack(padx = 2, pady = 2, expand='yes', fill='both') + + radiogroups = [] + self.var = Tkinter.IntVar() + self.var.set(0) + radioframe = Tkinter.Frame(parent) + w = Pmw.Group(radioframe, + tag_pyclass = Tkinter.Radiobutton, + tag_text='radiobutton 1', + tag_value = 0, + tag_variable = self.var) + w.pack(fill = 'both', expand = 1, side='left') + cw = Tkinter.Frame(w.interior(),width=200,height=20) + cw.pack(padx = 2, pady = 2, expand='yes', fill='both') + radiogroups.append(w) + + w = Pmw.Group(radioframe, + tag_pyclass = Tkinter.Radiobutton, + tag_text='radiobutton 2', + tag_font = Pmw.logicalfont('Helvetica', 4), + tag_value = 1, + tag_variable = self.var) + w.pack(fill = 'both', expand = 1, side='left') + cw = Tkinter.Frame(w.interior(),width=200,height=20) + cw.pack(padx = 2, pady = 2, expand='yes', fill='both') + radiogroups.append(w) + radioframe.pack(padx = 6, pady = 6, expand='yes', fill='both') + Pmw.aligngrouptags(radiogroups) + + w = Pmw.Group(parent, + tag_pyclass = Tkinter.Checkbutton, + tag_text='checkbutton', + tag_foreground='blue') + w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) + cw = Tkinter.Frame(w.interior(),width=150,height=20) + cw.pack(padx = 2, pady = 2, expand='yes', fill='both') + + w = Pmw.Group(parent, + tag_pyclass = Tkinter.Button, + tag_text='Tkinter.Button') + w.configure(tag_command = w.toggle) + w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) + cw = Tkinter.Label(w.interior(), + background = 'aliceblue', + text = 'A group with\na Button tag!?' + ) + cw.pack(padx = 2, pady = 2, expand='yes', fill='both') + + w = Pmw.Group(parent, + tag_pyclass = Tkinter.Button, + tag_text='Show/Hide') + w.configure(tag_command = w.toggle) + w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) + cw = Tkinter.Label(w.interior(), + background = 'aliceblue', + text = 'Now you see me.\nNow you don\'t.' + ) + cw.pack(padx = 2, pady = 2, expand='yes', fill='both') + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/HistoryText.py b/Pmw/Pmw_1_2/demos/HistoryText.py new file mode 100644 index 00000000..5a7b2eb4 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/HistoryText.py @@ -0,0 +1,102 @@ +title = 'Pmw.HistoryText demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack the PanedWidget to hold the query and result + # windows. + # !! panedwidget should automatically size to requested size + panedWidget = Pmw.PanedWidget(parent, + orient = 'vertical', + hull_height = 400, + hull_width = 550) + panedWidget.add('query', min = 0.05, size = 0.2) + panedWidget.add('buttons', min = 0.1, max = 0.1) + panedWidget.add('results', min = 0.05) + panedWidget.pack(fill = 'both', expand = 1) + + # Create and pack the HistoryText. + self.historyText = Pmw.HistoryText(panedWidget.pane('query'), + text_wrap = 'none', + text_width = 60, + text_height = 10, + historycommand = self.statechange, + ) + self.historyText.pack(fill = 'both', expand = 1) + self.historyText.component('text').focus() + + buttonList = ( + [20, None], + ['Clear', self.clear], + ['Undo', self.historyText.undo], + ['Redo', self.historyText.redo], + [20, None], + ['Prev', self.historyText.prev], + ['Next', self.historyText.next], + [30, None], + ['Execute', Pmw.busycallback(self.executeQuery)], + ) + self.buttonDict = {} + + buttonFrame = panedWidget.pane('buttons') + for text, cmd in buttonList: + if type(text) == type(69): + frame = Tkinter.Frame(buttonFrame, width = text) + frame.pack(side = 'left') + else: + button = Tkinter.Button(buttonFrame, text = text, command = cmd) + button.pack(side = 'left') + self.buttonDict[text] = button + + for text in ('Prev', 'Next'): + self.buttonDict[text].configure(state = 'disabled') + + self.results = Pmw.ScrolledText(panedWidget.pane('results'), text_wrap = 'none') + self.results.pack(fill = 'both', expand = 1) + + def statechange(self, prevstate, nextstate): + self.buttonDict['Prev'].configure(state = prevstate) + self.buttonDict['Next'].configure(state = nextstate) + + def clear(self): + self.historyText.delete('1.0', 'end') + + def addnewlines(self, text): + if len(text) == 1: + text = text + '\n' + if text[-1] != '\n': + text = text + '\n' + if text[-2] != '\n': + text = text + '\n' + return text + + def executeQuery(self): + sql = self.historyText.get() + self.results.insert('end', 'Query:\n' + self.addnewlines(sql)) + self.results.see('end') + self.results.update_idletasks() + self.historyText.addhistory() + results = 'Results:\nfoo' + if len(results) > 0: + self.results.insert('end', self.addnewlines(results)) + self.results.see('end') + + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/LabeledWidget.py b/Pmw/Pmw_1_2/demos/LabeledWidget.py new file mode 100644 index 00000000..8a98c59e --- /dev/null +++ b/Pmw/Pmw_1_2/demos/LabeledWidget.py @@ -0,0 +1,46 @@ +title = 'Pmw.LabeledWidget demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + + # Create a frame to put the LabeledWidgets into + frame = Tkinter.Frame(parent, background = 'grey90') + frame.pack(fill = 'both', expand = 1) + + # Create and pack the LabeledWidgets. + column = 0 + row = 0 + for pos in ('n', 'nw', 'wn', 'w'): + lw = Pmw.LabeledWidget(frame, + labelpos = pos, + label_text = pos + ' label') + lw.component('hull').configure(relief='sunken', borderwidth=2) + lw.grid(column=column, row=row, padx=10, pady=10) + cw = Tkinter.Button(lw.interior(), text='child\nsite') + cw.pack(padx=10, pady=10, expand='yes', fill='both') + + # Get ready for next grid position. + column = column + 1 + if column == 2: + column = 0 + row = row + 1 + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + widget = Demo(root) + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack() + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/LogicalFont.py b/Pmw/Pmw_1_2/demos/LogicalFont.py new file mode 100644 index 00000000..61854690 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/LogicalFont.py @@ -0,0 +1,84 @@ +title = 'Pmw LogicalFont demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import Tkinter +import Pmw + +class Demo: + + # The fonts to demonstrate. + fontList = ( + (('Times', 0), {}), + (('Helvetica', 0), {}), + (('Typewriter', 0), {}), + (('Fixed', 0), {}), + (('Courier', 0), {}), + (('Helvetica', 2), {'slant' : 'italic'}), + (('Helvetica', 0), {'size' : 18}), + (('Helvetica', 0), {'weight' : 'bold'}), + (('Helvetica', 12), {'weight' : 'bold', 'slant' : 'italic'}), + (('Typewriter', 0), {'size' : 8, 'weight' : 'bold'}), + (('Fixed', 0), {'size' : 8, 'weight' : 'bold'}), + (('Times', 0), {'size' : 24, 'weight' : 'bold', 'slant' : 'italic'}), + (('Typewriter', 0), {'width' : 'condensed'}), + (('Typewriter', -1), {'width' : 'condensed'}), + (('Fixed', 0), {'width' : 'condensed'}), + (('Fixed', -1), {'width' : 'condensed'}), + (('Helvetica', 0), {'weight' : 'bogus'}), + ) + + fontText = [] + + def __init__(self, parent): + + self.parent = parent + + # Create the text to display to the user to represent each font. + if Demo.fontText == []: + for args, dict in Demo.fontList: + text = args[0] + if args[1] != 0: + text = text + ' ' + str(args[1]) + for name, value in dict.items(): + text = text + ' ' + name + ': ' + str(value) + Demo.fontText.append(text) + + # Create a listbox to contain the font selections. + self.box = Pmw.ScrolledListBox(parent, listbox_selectmode='single', + listbox_width = 35, + listbox_height = 10, + items=Demo.fontText, + label_text='Font', labelpos='nw', + selectioncommand=self.selectionCommand) + self.box.pack(fill = 'both', expand = 1, padx = 10, pady = 10) + + # Create a label to display the selected font. + self.target = Tkinter.Label(parent, + text = 'The quick brown fox jumps\nover the lazy dog', + relief = 'sunken', padx = 10, pady = 10) + self.target.pack(fill = 'both', expand = 1, padx = 10, pady = 10) + + def selectionCommand(self): + sel = self.box.curselection() + if len(sel) > 0: + args, dict = Demo.fontList[string.atoi(sel[0])] + font = apply(Pmw.logicalfont, args, dict) + self.target.configure(font = font) + print font + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/MainMenuBar.py b/Pmw/Pmw_1_2/demos/MainMenuBar.py new file mode 100644 index 00000000..682d36ee --- /dev/null +++ b/Pmw/Pmw_1_2/demos/MainMenuBar.py @@ -0,0 +1,176 @@ +title = 'Pmw.MainMenuBar demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create button to launch the toplevel with main menubar. + w = Tkinter.Button(parent, text = 'Show Pmw.MainMenuBar demo', + command = lambda parent=parent: MainMenuBarToplevel(parent)) + w.pack(padx = 8, pady = 8) + +class MainMenuBarToplevel: + def __init__(self, parent): + # Create the toplevel to contain the main menubar. + megaToplevel = Pmw.MegaToplevel(parent, title = title) + toplevel = megaToplevel.interior() + + # Create the Balloon for this toplevel. + self.balloon = Pmw.Balloon(toplevel) + + # Create and install the MenuBar. + menuBar = Pmw.MainMenuBar(toplevel, + balloon = self.balloon) + toplevel.configure(menu = menuBar) + self.menuBar = menuBar + + # Add some buttons to the MainMenuBar. + menuBar.addmenu('File', 'Close this window or exit') + menuBar.addmenuitem('File', 'command', 'Close this window', + command = PrintOne('Action: close'), + label = 'Close') + menuBar.addmenuitem('File', 'separator') + menuBar.addmenuitem('File', 'command', 'Exit the application', + command = PrintOne('Action: exit'), + label = 'Exit') + + menuBar.addmenu('Edit', 'Cut, copy or paste') + menuBar.addmenuitem('Edit', 'command', 'Delete the current selection', + command = PrintOne('Action: delete'), + label = 'Delete') + + menuBar.addmenu('Options', 'Set user preferences') + menuBar.addmenuitem('Options', 'command', 'Set general preferences', + command = PrintOne('Action: general options'), + label = 'General...') + + # Create a checkbutton menu item. + self.toggleVar = Tkinter.IntVar() + # Initialise the checkbutton to 1: + self.toggleVar.set(1) + menuBar.addmenuitem('Options', 'checkbutton', 'Toggle me on/off', + label = 'Toggle', + command = self._toggleMe, + variable = self.toggleVar) + self._toggleMe() + + menuBar.addcascademenu('Options', 'Size', + 'Set some other preferences', traverseSpec = 'z', tearoff = 1) + for size in ('tiny', 'small', 'average', 'big', 'huge'): + menuBar.addmenuitem('Size', 'command', 'Set size to ' + size, + command = PrintOne('Action: size ' + size), + label = size) + + menuBar.addmenu('Help', 'User manuals', name = 'help') + menuBar.addmenuitem('Help', 'command', 'About this application', + command = PrintOne('Action: about'), + label = 'About...') + + # Create and pack the main part of the window. + self.mainPart = Tkinter.Label(toplevel, + text = 'This is the\nmain part of\nthe window', + background = 'black', + foreground = 'white', + padx = 30, + pady = 30) + self.mainPart.pack(fill = 'both', expand = 1) + + # Create and pack the MessageBar. + self.messageBar = Pmw.MessageBar(toplevel, + entry_width = 40, + entry_relief='groove', + labelpos = 'w', + label_text = 'Status:') + self.messageBar.pack(fill = 'x', padx = 10, pady = 10) + self.messageBar.message('state', + 'Balloon/status help not working properly - Tk menubar bug') + + buttonBox = Pmw.ButtonBox(toplevel) + buttonBox.pack(fill = 'x') + buttonBox.add('Disable\nall', command = menuBar.disableall) + buttonBox.add('Enable\nall', command = menuBar.enableall) + buttonBox.add('Create\nmenu', command = self.add) + buttonBox.add('Delete\nmenu', command = self.delete) + buttonBox.add('Create\nitem', command = self.additem) + buttonBox.add('Delete\nitem', command = self.deleteitem) + + # Configure the balloon to displays its status messages in the + # message bar. + self.balloon.configure(statuscommand = self.messageBar.helpmessage) + + self.testMenuList = [] + + def _toggleMe(self): + print 'Toggle value:', self.toggleVar.get() + + def add(self): + if len(self.testMenuList) == 0: + num = 0 + else: + num = self.testMenuList[-1] + num = num + 1 + name = 'Menu%d' % num + self.testMenuList.append(num) + + self.menuBar.addmenu(name, 'This is ' + name) + + def delete(self): + if len(self.testMenuList) == 0: + self.menuBar.bell() + else: + num = self.testMenuList[0] + name = 'Menu%d' % num + del self.testMenuList[0] + self.menuBar.deletemenu(name) + + def additem(self): + if len(self.testMenuList) == 0: + self.menuBar.bell() + else: + num = self.testMenuList[-1] + menuName = 'Menu%d' % num + menu = self.menuBar.component(menuName) + if menu.index('end') is None: + label = 'item X' + else: + label = menu.entrycget('end', 'label') + 'X' + self.menuBar.addmenuitem(menuName, 'command', 'Help for ' + label, + command = PrintOne('Action: ' + menuName + ': ' + label), + label = label) + + def deleteitem(self): + if len(self.testMenuList) == 0: + self.menuBar.bell() + else: + num = self.testMenuList[-1] + menuName = 'Menu%d' % num + menu = self.menuBar.component(menuName) + if menu.index('end') is None: + self.menuBar.bell() + else: + self.menuBar.deletemenuitems(menuName, 0) + +class PrintOne: + def __init__(self, text): + self.text = text + + def __call__(self): + print self.text + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/MenuBar.py b/Pmw/Pmw_1_2/demos/MenuBar.py new file mode 100644 index 00000000..8e22e53b --- /dev/null +++ b/Pmw/Pmw_1_2/demos/MenuBar.py @@ -0,0 +1,166 @@ +title = 'Pmw.MenuBar demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the Balloon. + self.balloon = Pmw.Balloon(parent) + + # Create and pack the MenuBar. + menuBar = Pmw.MenuBar(parent, + hull_relief = 'raised', + hull_borderwidth = 1, + balloon = self.balloon) + menuBar.pack(fill = 'x') + self.menuBar = menuBar + + # Add some buttons to the MenuBar. + menuBar.addmenu('File', 'Close this window or exit') + menuBar.addmenuitem('File', 'command', 'Close this window', + command = PrintOne('Action: close'), + label = 'Close') + menuBar.addmenuitem('File', 'separator') + menuBar.addmenuitem('File', 'command', 'Exit the application', + command = PrintOne('Action: exit'), + label = 'Exit') + + menuBar.addmenu('Edit', 'Cut, copy or paste') + menuBar.addmenuitem('Edit', 'command', 'Delete the current selection', + command = PrintOne('Action: delete'), + label = 'Delete') + + menuBar.addmenu('Options', 'Set user preferences') + menuBar.addmenuitem('Options', 'command', 'Set general preferences', + command = PrintOne('Action: general options'), + label = 'General...') + + # Create a checkbutton menu item. + self.toggleVar = Tkinter.IntVar() + # Initialise the checkbutton to 1: + self.toggleVar.set(1) + menuBar.addmenuitem('Options', 'checkbutton', 'Toggle me on/off', + label = 'Toggle', + command = self._toggleMe, + variable = self.toggleVar) + self._toggleMe() + + menuBar.addcascademenu('Options', 'Size', + 'Set some other preferences', traverseSpec = 'z', tearoff = 1) + for size in ('tiny', 'small', 'average', 'big', 'huge'): + menuBar.addmenuitem('Size', 'command', 'Set size to ' + size, + command = PrintOne('Action: size ' + size), + label = size) + + menuBar.addmenu('Help', 'User manuals', side = 'right') + menuBar.addmenuitem('Help', 'command', 'About this application', + command = PrintOne('Action: about'), + label = 'About...') + + # Create and pack the main part of the window. + self.mainPart = Tkinter.Label(parent, + text = 'This is the\nmain part of\nthe window', + background = 'black', + foreground = 'white', + padx = 30, + pady = 30) + self.mainPart.pack(fill = 'both', expand = 1) + + # Create and pack the MessageBar. + self.messageBar = Pmw.MessageBar(parent, + entry_width = 40, + entry_relief='groove', + labelpos = 'w', + label_text = 'Status:') + self.messageBar.pack(fill = 'x', padx = 10, pady = 10) + self.messageBar.message('state', 'OK') + + buttonBox = Pmw.ButtonBox(parent) + buttonBox.pack(fill = 'x') + buttonBox.add('Disable\nall', command = menuBar.disableall) + buttonBox.add('Enable\nall', command = menuBar.enableall) + buttonBox.add('Create\nmenu', command = self.add) + buttonBox.add('Delete\nmenu', command = self.delete) + buttonBox.add('Create\nitem', command = self.additem) + buttonBox.add('Delete\nitem', command = self.deleteitem) + + # Configure the balloon to displays its status messages in the + # message bar. + self.balloon.configure(statuscommand = self.messageBar.helpmessage) + + self.testMenuList = [] + + def _toggleMe(self): + print 'Toggle value:', self.toggleVar.get() + + def add(self): + if len(self.testMenuList) == 0: + num = 0 + else: + num = self.testMenuList[-1] + num = num + 1 + name = 'Menu%d' % num + self.testMenuList.append(num) + + self.menuBar.addmenu(name, 'This is ' + name) + + def delete(self): + if len(self.testMenuList) == 0: + self.menuBar.bell() + else: + num = self.testMenuList[0] + name = 'Menu%d' % num + del self.testMenuList[0] + self.menuBar.deletemenu(name) + + def additem(self): + if len(self.testMenuList) == 0: + self.menuBar.bell() + else: + num = self.testMenuList[-1] + menuName = 'Menu%d' % num + menu = self.menuBar.component(menuName + '-menu') + if menu.index('end') is None: + label = 'item X' + else: + label = menu.entrycget('end', 'label') + 'X' + self.menuBar.addmenuitem(menuName, 'command', 'Help for ' + label, + command = PrintOne('Action: ' + menuName + ': ' + label), + label = label) + + def deleteitem(self): + if len(self.testMenuList) == 0: + self.menuBar.bell() + else: + num = self.testMenuList[-1] + menuName = 'Menu%d' % num + menu = self.menuBar.component(menuName + '-menu') + if menu.index('end') is None: + self.menuBar.bell() + else: + self.menuBar.deletemenuitems(menuName, 0) + +class PrintOne: + def __init__(self, text): + self.text = text + + def __call__(self): + print self.text + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/MessageBar.py b/Pmw/Pmw_1_2/demos/MessageBar.py new file mode 100644 index 00000000..8cec7ddc --- /dev/null +++ b/Pmw/Pmw_1_2/demos/MessageBar.py @@ -0,0 +1,85 @@ +title = 'Pmw.MessageBar demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack the MessageBar. + self._messagebar = Pmw.MessageBar(parent, + entry_width = 40, + entry_relief='groove', + labelpos = 'w', + label_text = 'Status:') + self._messagebar.pack(side = 'bottom', fill = 'x', + expand = 1, padx = 10, pady = 10) + + # Create and pack the ScrolledListBox to change the MessageBar. + self.box = Pmw.ScrolledListBox(parent, + listbox_selectmode='single', + items=('state', 'help', 'userevent', 'systemevent', + 'usererror', 'systemerror', 'busy',), + label_text='Message type', + labelpos='n', + selectioncommand=self.selectionCommand) + self.box.pack(fill = 'both', expand = 'yes', padx = 10, pady = 10) + + self._index = 0 + self._stateCounter = 0 + + def selectionCommand(self): + sels = self.box.getcurselection() + if len(sels) > 0: + self._index = self._index + 1 + messagetype = sels[0] + if messagetype == 'state': + self._stateCounter = (self._stateCounter + 1) % 3 + text = stateMessages[self._stateCounter] + if text != '': + text = text + ' (' + messagetype + ')' + self._messagebar.message('state', text) + else: + text = messages[messagetype] + text = text + ' (' + messagetype + ')' + self._messagebar.message(messagetype, text) + if messagetype == 'busy': + Pmw.showbusycursor() + self.box.after(2000) + Pmw.hidebusycursor() + self._messagebar.resetmessages('busy') + text = 'All files successfully removed' + text = text + ' (userevent)' + self._messagebar.message('userevent', text) + + +messages = { + 'help': 'Save current file', + 'userevent': 'Saving file "foo"', + 'busy': 'Busy deleting all files from file system ...', + 'systemevent': 'File "foo" saved', + 'usererror': 'Invalid file name "foo/bar"', + 'systemerror': 'Failed to save file: file system full', +} + +stateMessages = { + 0: '', + 1: 'Database is down', + 2: 'Waiting for reply from database', +} + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/MessageDialog.py b/Pmw/Pmw_1_2/demos/MessageDialog.py new file mode 100644 index 00000000..09c8c98b --- /dev/null +++ b/Pmw/Pmw_1_2/demos/MessageDialog.py @@ -0,0 +1,102 @@ +title = 'Pmw.MessageDialog demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + self.parent = parent + + # Create dialog 1. + self.dialog1 = Pmw.MessageDialog(parent, + title = 'Simple message dialog', + defaultbutton = 0, + message_text = 'A simple message dialog\nwith no callback.') + self.dialog1.iconname('Simple message dialog') + self.dialog1.withdraw() + + # Create dialog 2. + self.dialog2 = Pmw.MessageDialog(parent, + title = 'Bell ringing dialog', + message_text = 'This message dialog\nwill ring the bell ' + + 'when\nyou click on the buttons.', + iconpos = 'w', + icon_bitmap = 'error', + command = self.execute2, + buttons = ('One', 'Two', 'Three', 'Close')) + self.dialog2.iconname('Bell ringing dialog') + self.dialog2.withdraw() + + # Create dialog 3. + self.dialog3 = Pmw.MessageDialog(parent, + title = 'Vertical button dialog', + message_text = 'This message dialog\nhas the buttons on the\n' + + 'right hand side.', + buttonboxpos = 'e', + iconpos = 'n', + icon_bitmap = 'warning', + buttons = ('Goodbye', 'Au revoir', 'Sayonara', 'Close'), + defaultbutton = 'Close') + self.dialog3.iconname('Vertical button dialog') + self.dialog3.withdraw() + + # Create some buttons to launch the dialogs. + w = Tkinter.Button(parent, text = 'Simple dialog', + command = lambda self = self: + self.dialog1.activate(geometry = 'first+100+100')) + w.pack(padx = 8, pady = 8) + + w = Tkinter.Button(parent, text = 'Bell ringing dialog', + command = self.dialog2.activate) + w.pack(padx = 8, pady = 8) + + w = Tkinter.Button(parent, text = 'Vertical buttons', + command = self.dialog3.activate) + w.pack(padx = 8, pady = 8) + + w = Tkinter.Button(parent, text = 'On the fly dialog', + command = self._createOnTheFly) + w.pack(padx = 8, pady = 8) + + def execute2(self, result): + print 'You clicked on', result + if result is None: + self.dialog2.deactivate(result) + elif result == 'Close': + self.dialog2.deactivate(result) + else: + for count in range({'One': 1, 'Two': 2, 'Three': 3}[result]): + if count != 0: + self.dialog2.after(200) + self.dialog2.bell() + + def _createOnTheFly(self): + dialog = Pmw.MessageDialog(self.parent, + title = 'On the fly dialog', + defaultbutton = 0, + buttons = ('OK', 'Apply', 'Cancel', 'Help'), + message_text = 'This dialog was created when you clicked ' + + 'on the button.') + dialog.iconname('Simple message dialog') + result = dialog.activate() + + print 'You selected', result + + + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/MessageInfo.py b/Pmw/Pmw_1_2/demos/MessageInfo.py new file mode 100644 index 00000000..1c2fac40 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/MessageInfo.py @@ -0,0 +1,108 @@ +title = 'Pmw toplevel megawidget demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class MessageInfo(Pmw.MegaToplevel): + + # Demo Pmw toplevel megawidget. + + def __init__(self, parent=None, **kw): + + # Define the megawidget options. + optiondefs = () + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaToplevel.__init__(self, parent) + + # Create the components. + interior = self.interior() + + self._dismiss = self.createcomponent('dismiss', + (), None, + Tkinter.Button, (interior,), + text = 'Dismiss', + command = self.goodbye) + self._dismiss.pack(side = 'bottom', pady = 4) + + self._separator = self.createcomponent('separator', + (), None, + Tkinter.Frame, (interior,), + height = 2, + borderwidth = 1, + relief = 'sunken') + self._separator.pack(side = 'bottom', fill = 'x', pady = 4) + + self._icon = self.createcomponent('icon', + (), None, + Tkinter.Label, (interior,)) + self._icon.pack(side = 'left', padx = 8, pady = 8) + + self._infoFrame = self.createcomponent('infoframe', + (), None, + Tkinter.Frame, (interior,)) + self._infoFrame.pack( + side = 'left', + fill = 'both', + expand = 1, + padx = 4, + pady = 4) + + self._message = self.createcomponent('message', + (), None, + Tkinter.Label, (interior,)) + self._message.pack(expand = 1, fill = 'both', padx = 10, pady = 10) + + self.bind('', self.goodbye) + + # Check keywords and initialise options. + self.initialiseoptions() + + def goodbye(self, event = None): + self.destroy() + +class Demo: + def __init__(self, parent): + # Create button to launch the megawidget. + self.button = Tkinter.Button(parent, + command = self.showMessageInfo, + text = 'Show toplevel megawidget') + self.button.pack(padx = 8, pady = 8) + + self.count = 0 + self.parent = parent + + def showMessageInfo(self): + bitmaps = ('warning', 'hourglass', 'error', 'info', + 'gray25', 'gray50', 'question', 'questhead') + bitmap = bitmaps[self.count % len(bitmaps)] + + message = 'This is a demonstration of\na megawidget.\n' + \ + 'It contains a configurable\nmessage area and bitmap.\n' + \ + 'This instance is displaying\nthe "' + bitmap + '" bitmap.' + + # Make the toplevel window a child of this window, so that it + # is destroyed when the demo is destroyed. + MessageInfo(self.parent, message_text = message, icon_bitmap = bitmap) + + self.count = self.count + 1 + if self.count == 1: + self.button.configure(text = 'Show another\ntoplevel megawidget') + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/MultiLineLabel.py b/Pmw/Pmw_1_2/demos/MultiLineLabel.py new file mode 100644 index 00000000..b08b4c15 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/MultiLineLabel.py @@ -0,0 +1,73 @@ +title = 'Multi-line label demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + + frame = Tkinter.Frame(parent, background = '#eeeeee') + frame.pack(fill = 'both', expand = 1, padx = 5, pady = 5) + + stickys = ('n', 's', 'e', 'w', 'ns', 'ew', 'ne', 'nw', 'se', 'sw', + 'nsw', 'nse', 'new', 'sew', 'nsew',) + + widgets = [] + row = 0 + column = 0 + + # Choose one megawidget class to demonstrate: + cls = Pmw.EntryField + # cls = Pmw.Counter + # cls = Pmw.ComboBox + # cls = Pmw.LabeledWidget + # cls = Pmw.MessageBar + + for sticky in stickys: + dict = {} + dict['sticky'] = sticky + dict['labelpos'] = 'w' + dict['label_text'] = '1\n' + sticky + ':\n3' + if cls == Pmw.EntryField: + dict['value'] = sticky + dict['entry_width'] = 6 + if cls == Pmw.Counter or cls == Pmw.ComboBox: + dict['entryfield_value'] = sticky + dict['entry_width'] = 6 + widget = apply(cls, (frame,), dict) + if cls == Pmw.LabeledWidget: + f = Tkinter.Button(widget.interior(), text = sticky) + f.pack(fill = 'both', expand = 1) + if cls == Pmw.MessageBar: + widget.message('state', sticky) + widget.grid(column=column, row=row, sticky='ew', padx = 10, pady = 5) + frame.grid_columnconfigure(column, weight=1) + frame.grid_rowconfigure(row, weight=1) + + widgets.append(widget) + + if row < 4: + row = row + 1 + else: + row = 0 + column = column + 1 + + Pmw.alignlabels(widgets, sticky = 'e') + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/NestedDialogs.py b/Pmw/Pmw_1_2/demos/NestedDialogs.py new file mode 100644 index 00000000..e8199a33 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/NestedDialogs.py @@ -0,0 +1,71 @@ +title = 'Modal dialog nesting demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create button to launch the dialog. + w = Tkinter.Button(parent, text = 'Show first dialog', + command = self.showFirstDialog) + w.pack(padx = 8, pady = 8) + + self.timerId = None + + self.dialog1 = Pmw.MessageDialog(parent, + message_text = 'This is the first modal dialog.\n' + + 'You can see how dialogs nest by\n' + + 'clicking on the "Next" button.', + title = 'Dialog 1', + buttons = ('Next', 'Cancel'), + defaultbutton = 'Next', + command = self.next_dialog) + self.dialog1.withdraw() + + self.dialog2 = Pmw.Dialog(self.dialog1.interior(), + title = 'Dialog 2', + buttons = ('Cancel',), + deactivatecommand = self.cancelTimer, + defaultbutton = 'Cancel') + self.dialog2.withdraw() + w = Tkinter.Label(self.dialog2.interior(), + text = 'This is the second modal dialog.\n' + + 'It will automatically disappear shortly') + w.pack(padx = 10, pady = 10) + + def showFirstDialog(self): + self.dialog1.activate() + + def cancelTimer(self): + if self.timerId is not None: + self.dialog2.after_cancel(self.timerId) + self.timerId = None + + def deactivateSecond(self): + self.timerId = None + self.dialog2.deactivate() + + def next_dialog(self, result): + if result != 'Next': + self.dialog1.deactivate() + return + + self.timerId = self.dialog2.after(3000, self.deactivateSecond) + self.dialog2.activate() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/NoteBook.py b/Pmw/Pmw_1_2/demos/NoteBook.py new file mode 100644 index 00000000..20815a51 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/NoteBook.py @@ -0,0 +1,52 @@ +title = 'Pmw.NoteBook demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack the NoteBook. + notebook = Pmw.NoteBook(parent) + notebook.pack(fill = 'both', expand = 1, padx = 10, pady = 10) + + # Add the "Appearance" page to the notebook. + page = notebook.add('Appearance') + notebook.tab('Appearance').focus_set() + + # Create the "Toolbar" contents of the page. + group = Pmw.Group(page, tag_text = 'Toolbar') + group.pack(fill = 'both', expand = 1, padx = 10, pady = 10) + b1 = Tkinter.Checkbutton(group.interior(), text = 'Show toolbar') + b1.grid(row = 0, column = 0) + b2 = Tkinter.Checkbutton(group.interior(), text = 'Toolbar tips') + b2.grid(row = 0, column = 1) + + # Create the "Startup" contents of the page. + group = Pmw.Group(page, tag_text = 'Startup') + group.pack(fill = 'both', expand = 1, padx = 10, pady = 10) + home = Pmw.EntryField(group.interior(), labelpos = 'w', + label_text = 'Home page location:') + home.pack(fill = 'x', padx = 20, pady = 10) + + # Add two more empty pages. + page = notebook.add('Helpers') + page = notebook.add('Images') + + notebook.setnaturalsize() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + widget = Demo(root) + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack() + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/NoteBook_2.py b/Pmw/Pmw_1_2/demos/NoteBook_2.py new file mode 100644 index 00000000..f42037a7 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/NoteBook_2.py @@ -0,0 +1,224 @@ +title = 'Pmw.NoteBook demonstration (more complex)' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent, withTabs = 1): + + # Repeat random number sequence for each run. + self.rand = 12345 + + # Default demo is to display a tabbed notebook. + self.withTabs = withTabs + + # Create a frame to put everything in + self.mainframe = Tkinter.Frame(parent) + self.mainframe.pack(fill = 'both', expand = 1) + + # Find current default colors + button = Tkinter.Button() + defaultbg = button.cget('background') + defaultfg = button.cget('foreground') + button.destroy() + + # Create the list of colors to cycle through + self.colorList = [] + self.colorList.append((defaultbg, defaultfg)) + self.colorIndex = 0 + for color in Pmw.Color.spectrum(6, 1.5, 1.0, 1.0, 1): + bg = Pmw.Color.changebrightness(self.mainframe, color, 0.85) + self.colorList.append((bg, 'black')) + bg = Pmw.Color.changebrightness(self.mainframe, color, 0.55) + self.colorList.append((bg, 'white')) + + # Set the color to the current default + Pmw.Color.changecolor(self.mainframe, defaultbg, foreground = defaultfg) + defaultPalette = Pmw.Color.getdefaultpalette(self.mainframe) + Pmw.Color.setscheme(self.mainframe, defaultbg, foreground = defaultfg) + + # Create the notebook, but don't pack it yet. + if self.withTabs: + tabpos = 'n' + else: + tabpos = None + self.notebook = Pmw.NoteBook(self.mainframe, + tabpos = tabpos, + createcommand = PrintOne('Create'), + lowercommand = PrintOne('Lower'), + raisecommand = PrintOne('Raise'), + hull_width = 300, + hull_height = 200, + ) + + # Create a buttonbox to configure the notebook and pack it first. + buttonbox = Pmw.ButtonBox(self.mainframe) + buttonbox.pack(side = 'bottom', fill = 'x') + + # Add some buttons to the buttonbox to configure the notebook. + buttonbox.add('Insert\npage', command = self.insertpage) + buttonbox.add('Delete\npage', command = self.deletepage) + buttonbox.add('Add\nbutton', command = self.addbutton) + buttonbox.add('Change\ncolor', command = self.changecolor) + buttonbox.add('Natural\nsize', command = + self.notebook.setnaturalsize) + + if not self.withTabs: + # Create the selection widget to select the page in the notebook. + self.optionmenu = Pmw.OptionMenu(self.mainframe, + menubutton_width = 10, + command = self.notebook.selectpage + ) + self.optionmenu.pack(side = 'left', padx = 10) + + # Pack the notebook last so that the buttonbox does not disappear + # when the window is made smaller. + self.notebook.pack(fill = 'both', expand = 1, padx = 5, pady = 5) + + # Populate some pages of the notebook. + page = self.notebook.add('tmp') + self.notebook.delete('tmp') + page = self.notebook.add('Appearance') + if self.withTabs: + self.notebook.tab('Appearance').focus_set() + button = Tkinter.Button(page, + text = 'Welcome\nto\nthe\nAppearance\npage') + button.pack(expand = 1) + page = self.notebook.add('Fonts') + button = Tkinter.Button(page, + text = 'This is a very very very very wide Fonts page') + button.pack(expand = 1) + page = self.notebook.insert('Applications', before = 'Fonts') + button = Tkinter.Button(page, text = 'This is the Applications page') + button.pack(expand = 1) + + # Initialise the first page and the initial colour. + if not self.withTabs: + self.optionmenu.setitems(self.notebook.pagenames()) + apply(Pmw.Color.setscheme, (self.mainframe,), defaultPalette) + self.pageCounter = 0 + + def insertpage(self): + # Create a page at a random position + + defaultPalette = Pmw.Color.getdefaultpalette(self.mainframe) + bg, fg = self.colorList[self.colorIndex] + Pmw.Color.setscheme(self.mainframe, bg, foreground = fg) + + self.pageCounter = self.pageCounter + 1 + before = self.randomchoice(self.notebook.pagenames() + [Pmw.END]) + pageName = 'page%d' % self.pageCounter + if self.pageCounter % 5 == 0: + tab_text = pageName + '\nline two' + else: + tab_text = pageName + classes = (None, Tkinter.Button, Tkinter.Label, Tkinter.Checkbutton) + cls = self.randomchoice((None,) + classes) + if cls is None: + print 'Adding', pageName, 'as a frame with a button' + if self.withTabs: + page = self.notebook.insert(pageName, before, tab_text = tab_text) + else: + page = self.notebook.insert(pageName, before) + button = Tkinter.Button(page, + text = 'This is button %d' % self.pageCounter) + button.pack(expand = 1) + else: + print 'Adding', pageName, 'using', cls + if self.withTabs: + page = self.notebook.insert(pageName, before, + tab_text = tab_text, + page_pyclass = cls, + page_text = 'This is a page using\na %s' % str(cls) + ) + else: + page = self.notebook.insert(pageName, before, + page_pyclass = cls, + page_text = 'This is a page using\na %s' % str(cls) + ) + if not self.withTabs: + self.optionmenu.setitems( + self.notebook.pagenames(), self.notebook.getcurselection()) + + apply(Pmw.Color.setscheme, (self.mainframe,), defaultPalette) + + def addbutton(self): + # Add a button to a random page. + + defaultPalette = Pmw.Color.getdefaultpalette(self.mainframe) + bg, fg = self.colorList[self.colorIndex] + Pmw.Color.setscheme(self.mainframe, bg, foreground = fg) + + framePages = [] + for pageName in self.notebook.pagenames(): + page = self.notebook.page(pageName) + if page.__class__ == Tkinter.Frame: + framePages.append(pageName) + + if len(framePages) == 0: + self.notebook.bell() + return + + pageName = self.randomchoice(framePages) + print 'Adding extra button to', pageName + page = self.notebook.page(pageName) + button = Tkinter.Button(page, text = 'This is an extra button') + button.pack(expand = 1) + + apply(Pmw.Color.setscheme, (self.mainframe,), defaultPalette) + + def deletepage(self): + # Delete a random page + + pageNames = self.notebook.pagenames() + if len(pageNames) == 0: + self.notebook.bell() + return + + pageName = self.randomchoice(pageNames) + print 'Deleting', pageName + self.notebook.delete(pageName) + if not self.withTabs: + self.optionmenu.setitems( + self.notebook.pagenames(), self.notebook.getcurselection()) + + def changecolor(self): + self.colorIndex = self.colorIndex + 1 + if self.colorIndex == len(self.colorList): + self.colorIndex = 0 + + bg, fg = self.colorList[self.colorIndex] + print 'Changing color to', bg + Pmw.Color.changecolor(self.mainframe, bg, foreground = fg) + self.notebook.recolorborders() + + # Simple random number generator. + def randomchoice(self, selection): + num = len(selection) + self.rand = (self.rand * 125) % 2796203 + index = self.rand % num + return selection[index] + +class PrintOne: + def __init__(self, text): + self.text = text + + def __call__(self, text): + print self.text, text + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + widget = Demo(root) + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack() + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/NoteBook_3.py b/Pmw/Pmw_1_2/demos/NoteBook_3.py new file mode 100644 index 00000000..8106c5af --- /dev/null +++ b/Pmw/Pmw_1_2/demos/NoteBook_3.py @@ -0,0 +1,26 @@ +title = 'Pmw.NoteBook demonstration (with no tabs)' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +# Reuse the NoteBook with tabs demo. +import NoteBook_2 + +class Demo(NoteBook_2.Demo): + def __init__(self, parent): + NoteBook_2.Demo.__init__(self, parent, withTabs = 0) + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + widget = Demo(root) + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack() + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/OptionMenu.py b/Pmw/Pmw_1_2/demos/OptionMenu.py new file mode 100644 index 00000000..11d7a88a --- /dev/null +++ b/Pmw/Pmw_1_2/demos/OptionMenu.py @@ -0,0 +1,66 @@ +title = 'Pmw.OptionMenu demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack the OptionMenu megawidgets. + # The first one has a textvariable. + self.var = Tkinter.StringVar() + self.var.set('steamed') + self.method_menu = Pmw.OptionMenu(parent, + labelpos = 'w', + label_text = 'Choose method:', + menubutton_textvariable = self.var, + items = ['baked', 'steamed', 'stir fried', 'boiled', 'raw'], + menubutton_width = 10, + ) + self.method_menu.pack(anchor = 'w', padx = 10, pady = 10) + + self.vege_menu = Pmw.OptionMenu (parent, + labelpos = 'w', + label_text = 'Choose vegetable:', + items = ('broccoli', 'peas', 'carrots', 'pumpkin'), + menubutton_width = 10, + command = self._printOrder, + ) + self.vege_menu.pack(anchor = 'w', padx = 10, pady = 10) + + self.direction_menu = Pmw.OptionMenu (parent, + labelpos = 'w', + label_text = 'Menu direction:', + items = ('flush', 'above', 'below', 'left', 'right'), + menubutton_width = 10, + command = self._changeDirection, + ) + self.direction_menu.pack(anchor = 'w', padx = 10, pady = 10) + + menus = (self.method_menu, self.vege_menu, self.direction_menu) + Pmw.alignlabels(menus) + + def _printOrder(self, vege): + # Can use 'self.var.get()' instead of 'getcurselection()'. + print 'You have chosen %s %s.' % \ + (self.method_menu.getcurselection(), vege) + + def _changeDirection(self, direction): + for menu in (self.method_menu, self.vege_menu, self.direction_menu): + menu.configure(menubutton_direction = direction) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/PanedWidget.py b/Pmw/Pmw_1_2/demos/PanedWidget.py new file mode 100644 index 00000000..e8bdb22d --- /dev/null +++ b/Pmw/Pmw_1_2/demos/PanedWidget.py @@ -0,0 +1,103 @@ +title = 'Pmw.PanedWidget demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + + # Create a main PanedWidget with a few panes. + self.pw = Pmw.PanedWidget(parent, + orient='vertical', + hull_borderwidth = 1, + hull_relief = 'sunken', + hull_width=300, + hull_height=400) + for self.numPanes in range(4): + if self.numPanes == 1: + name = 'Fixed size' + pane = self.pw.add(name, min = .1, max = .1) + else: + name = 'Pane ' + str(self.numPanes) + pane = self.pw.add(name, min = .1, size = .25) + label = Tkinter.Label(pane, text = name) + label.pack(side = 'left', expand = 1) + button = Tkinter.Button(pane, text = 'Delete', + command = lambda s=self, n=name: s.deletePane(n)) + button.pack(side = 'left', expand = 1) + # TODO: add buttons to invoke self.moveOneUp and self.moveOneUp. + + self.pw.pack(expand = 1, fill='both') + + buttonBox = Pmw.ButtonBox(parent) + buttonBox.pack(fill = 'x') + buttonBox.add('Add pane', command = self.addPane) + buttonBox.add('Move pane', command = self.move) + self.moveSrc = 0 + self.moveNewPos = 1 + self.moveBack = 0 + + def move(self): + numPanes = len(self.pw.panes()) + if numPanes == 0: + print 'No panes to move!' + return + + if self.moveSrc >= numPanes: + self.moveSrc = numPanes - 1 + if self.moveNewPos >= numPanes: + self.moveNewPos = numPanes - 1 + print 'Moving pane', self.moveSrc, 'to new position', self.moveNewPos + self.pw.move(self.moveSrc, self.moveNewPos) + + self.moveSrc, self.moveNewPos = self.moveNewPos, self.moveSrc + if self.moveBack: + if self.moveNewPos == numPanes - 1: + self.moveNewPos = 0 + if self.moveSrc == numPanes - 1: + self.moveSrc = 0 + else: + self.moveSrc = self.moveSrc + 1 + else: + self.moveNewPos = self.moveNewPos + 1 + self.moveBack = not self.moveBack + + def addPane(self): + self.numPanes = self.numPanes + 1 + name = 'Pane ' + str(self.numPanes) + print 'Adding', name + pane = self.pw.add(name, min = .1, size = .25) + label = Tkinter.Label(pane, text = name) + label.pack(side = 'left', expand = 1) + button = Tkinter.Button(pane, text = 'Delete', + command = lambda s=self, n=name: s.deletePane(n)) + button.pack(side = 'left', expand = 1) + self.pw.updatelayout() + + def deletePane(self, name): + print 'Deleting', name + self.pw.delete(name) + self.pw.updatelayout() + + def moveOneUp(self, name): + self.pw.move(name, name, -1) + + def moveOneDown(self, name): + self.pw.move(name, name, 1) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/PanedWidget_2.py b/Pmw/Pmw_1_2/demos/PanedWidget_2.py new file mode 100644 index 00000000..334bced0 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/PanedWidget_2.py @@ -0,0 +1,65 @@ +title = 'Pmw.PanedWidget demonstration (pane factory)' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + self.paneCount = 0 + + # Create a "pane factory". + label = Tkinter.Label(parent, + pady = 10, + text = 'Below is a simple "pane factory".\n' + + 'Drag the handle on the left\nto create new panes.') + label.pack() + self.factory = Pmw.PanedWidget(parent, + orient='horizontal', + command = self.resize, + hull_borderwidth = 1, + hull_relief = 'raised', + hull_width=300, hull_height=200 + ) + self.factory.add('starter', size = 0.0) + self.factory.add('main') + button = Tkinter.Button(self.factory.pane('main'), + text = 'Pane\n0') + button.pack(expand = 1) + self.factory.pack(expand = 1, fill = 'both') + + def resize(self, list): + # Remove any panes less than 2 pixel wide. + for i in range(len(list) - 1, 0, -1): + if list[i] < 2: + self.factory.delete(i) + + # If the user has dragged the left hand handle, create a new pane. + if list[0] > 1: + self.paneCount = self.paneCount + 1 + + # Add a button to the new pane. + name = self.factory.panes()[0] + text = 'Pane\n' + str(self.paneCount) + button = Tkinter.Button(self.factory.pane(name), text = text) + button.pack(expand = 1) + + # Create a new starter pane. + name = 'Pane ' + str(self.paneCount) + self.factory.insert(name, size=0.0) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/PromptDialog.py b/Pmw/Pmw_1_2/demos/PromptDialog.py new file mode 100644 index 00000000..40f50f7d --- /dev/null +++ b/Pmw/Pmw_1_2/demos/PromptDialog.py @@ -0,0 +1,62 @@ +title = 'Pmw.PromptDialog demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +# This may demonstrate a bug in Tk. Click on Cancel in the confirm +# dialog and then click on OK in the password dialog. Under Solaris +# 2.5 and python 1.5, the Cancel button in the confirm dialog is still +# displayed active, that is, it has a lighter background. + +class Demo: + def __init__(self, parent): + # Create the dialog to prompt for the password. + self.dialog = Pmw.PromptDialog(parent, + title = 'Password', + label_text = 'Password:', + entryfield_labelpos = 'n', + entry_show = '*', + defaultbutton = 0, + buttons = ('OK', 'Cancel'), + command = self.execute) + self.dialog.withdraw() + + # Create the confirmation dialog. + self.confirm = Pmw.MessageDialog( + title = 'Are you sure?', + message_text = 'Are you really sure?', + defaultbutton = 0, + buttons = ('OK', 'Cancel')) + self.confirm.withdraw() + + # Create button to launch the dialog. + w = Tkinter.Button(parent, text = 'Show prompt dialog', + command = self.dialog.activate) + w.pack(padx = 8, pady = 8) + + def execute(self, result): + if result is None or result == 'Cancel': + print 'Password prompt cancelled' + self.dialog.deactivate(result) + else: + result = self.confirm.activate() + if result == 'OK': + print 'Password entered ' + self.dialog.get() + self.dialog.deactivate() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/RadioSelect.py b/Pmw/Pmw_1_2/demos/RadioSelect.py new file mode 100644 index 00000000..fb549b72 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/RadioSelect.py @@ -0,0 +1,116 @@ +title = 'Pmw.RadioSelect demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack a horizontal RadioSelect widget. + horiz = Pmw.RadioSelect(parent, + labelpos = 'w', + command = self.callback, + label_text = 'Horizontal', + frame_borderwidth = 2, + frame_relief = 'ridge' + ) + horiz.pack(fill = 'x', padx = 10, pady = 10) + + # Add some buttons to the horizontal RadioSelect. + for text in ('Fruit', 'Vegetables', 'Cereals', 'Legumes'): + horiz.add(text) + horiz.invoke('Cereals') + + # Create and pack a multiple selection RadioSelect widget. + self.multiple = Pmw.RadioSelect(parent, + labelpos = 'w', + command = self.multcallback, + label_text = 'Multiple\nselection', + frame_borderwidth = 2, + frame_relief = 'ridge', + selectmode = 'multiple', + ) + self.multiple.pack(fill = 'x', padx = 10) + + # Add some buttons to the multiple selection RadioSelect. + for text in ('Apricots', 'Eggplant', 'Rice', 'Lentils'): + self.multiple.add(text) + self.multiple.invoke('Rice') + + # Create and pack a vertical RadioSelect widget, with checkbuttons. + self.checkbuttons = Pmw.RadioSelect(parent, + buttontype = 'checkbutton', + orient = 'vertical', + labelpos = 'w', + command = self.checkbuttoncallback, + label_text = 'Vertical,\nusing\ncheckbuttons', + hull_borderwidth = 2, + hull_relief = 'ridge', + ) + self.checkbuttons.pack(side = 'left', expand = 1, padx = 10, pady = 10) + + # Add some buttons to the checkbutton RadioSelect. + for text in ('Male', 'Female'): + self.checkbuttons.add(text) + self.checkbuttons.invoke('Male') + self.checkbuttons.invoke('Female') + + # Create and pack a RadioSelect widget, with radiobuttons. + radiobuttons = Pmw.RadioSelect(parent, + buttontype = 'radiobutton', + orient = 'vertical', + labelpos = 'w', + command = self.callback, + label_text = 'Vertical,\nusing\nradiobuttons', + hull_borderwidth = 2, + hull_relief = 'ridge', + ) + radiobuttons.pack(side = 'left', expand = 1, padx = 10, pady = 10) + + # Add some buttons to the radiobutton RadioSelect. + for text in ('Male', 'Female', 'Both', 'Neither'): + radiobuttons.add(text) + radiobuttons.invoke('Both') + + def callback(self, tag): + # This is called whenever the user clicks on a button + # in a single select RadioSelect widget. + print 'Button', tag, 'was pressed.' + + def multcallback(self, tag, state): + # This is called whenever the user clicks on a button + # in the multiple select RadioSelect widget. + if state: + action = 'pressed.' + else: + action = 'released.' + + print 'Button', tag, 'was', action, \ + 'Selection:', self.multiple.getcurselection() + + def checkbuttoncallback(self, tag, state): + # This is called whenever the user clicks on a button + # in the checkbutton RadioSelect widget. + if state: + action = 'pressed.' + else: + action = 'released.' + + print 'Button', tag, 'was', action, \ + 'Selection:', self.checkbuttons.getcurselection() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/Resources.py b/Pmw/Pmw_1_2/demos/Resources.py new file mode 100644 index 00000000..2168b4ac --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Resources.py @@ -0,0 +1,74 @@ +title = 'Using Tk option database to configure Tk widgets' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import Tkinter +import Pmw + +info = """ + The Tk widgets contained in this + simple megawidget have been + configured using the Tk option + database. + *DemoClass*Listbox.cursor is 'heart' + *DemoClass*Entry.cursor is 'hand1' + *DemoClass*background is 'pink' + *DemoClass*highlightBackground is 'green' + *DemoClass*foreground is 'blue' +""" + +class DemoClass(Pmw.MegaWidget): + + # Demo Pmw megawidget. + + def __init__(self, parent = None, **kw): + + # Define the megawidget options. + optiondefs = () + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaWidget.__init__(self, parent) + + interior = self.interior() + listbox = Tkinter.Listbox(interior, height = 12, width = 40) + listbox.pack(fill='both', expand='yes') + for line in string.split(info, '\n'): + listbox.insert('end', line) + + entry = Tkinter.Entry(interior) + entry.pack(fill='y') + entry.insert(0, 'Hello, World!') + + # Check keywords and initialise options. + self.initialiseoptions() + +class Demo: + def __init__(self, parent): + + # Test Tk option database settings. + parent.option_add('*DemoClass*Listbox.cursor', 'heart') + parent.option_add('*DemoClass*Entry.cursor', 'hand1') + parent.option_add('*DemoClass*background', 'pink') + parent.option_add('*DemoClass*highlightBackground', 'green') + parent.option_add('*DemoClass*foreground', 'blue') + + # Create and pack the megawidget. + demo = DemoClass(parent) + demo.pack(fill = 'both', expand = 1) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/Resources_Pmw.py b/Pmw/Pmw_1_2/demos/Resources_Pmw.py new file mode 100644 index 00000000..a1f2f992 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Resources_Pmw.py @@ -0,0 +1,110 @@ +title = 'Using Tk option database to configure Pmw megawidgets' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + self.parent = parent + + header = Tkinter.Label(parent, text = 'Select some Tk option ' + + 'database values from\nthe lists, then click ' + + '\'Create dialog\' to create\na MessageDialog with ' + + 'these values as defaults.') + header.pack(padx = 10, pady = 10) + + # Create and pack the ComboBoxes to select options. + buttons = ( + "('OK',)", + "('Read', 'Write')", + "('OK', 'Cancel')", + "('OK', 'Apply', 'Cancel', 'Help')", + ) + + if Tkinter.TkVersion >= 8.4: + disabledState = 'readonly' + else: + disabledState = 'disabled' + + self._buttons = Pmw.ComboBox(parent, label_text = 'buttons:', + labelpos = 'w', + entry_state = disabledState, + scrolledlist_items = buttons) + self._buttons.pack(fill = 'x', expand = 1, padx = 8, pady = 8) + self._buttons.selectitem(3) + + buttonboxpos = ('n', 's', 'e', 'w',) + self._buttonboxpos = Pmw.ComboBox(parent, label_text = 'buttonboxpos:', + labelpos = 'w', + entry_state = disabledState, + scrolledlist_items = buttonboxpos) + self._buttonboxpos.pack(fill = 'x', expand = 1, padx = 8, pady = 8) + self._buttonboxpos.selectitem(2) + + pad = ('0', '8', '20', '50',) + self._pad = Pmw.ComboBox(parent, label_text = 'padx, pady:', + labelpos = 'w', + entry_state = disabledState, + scrolledlist_items = pad) + self._pad.pack(fill = 'x', expand = 1, padx = 8, pady = 8) + self._pad.selectitem(1) + + Pmw.alignlabels((self._buttons, self._buttonboxpos, self._pad)) + + # Create button to launch the dialog. + w = Tkinter.Button(parent, text = 'Create dialog', + command = self._createDialog) + w.pack(padx = 8, pady = 8) + + self.dialog = None + + def _createDialog(self): + + # Set the option database. + buttons = self._buttons.get() + buttonboxpos = self._buttonboxpos.get() + pad = self._pad.get() + self.parent.option_add('*MessageDialog.buttons', buttons) + self.parent.option_add('*MessageDialog.buttonboxpos', buttonboxpos) + self.parent.option_add('*ButtonBox.padx', pad) + self.parent.option_add('*ButtonBox.pady', pad) + + # Create the dialog. + if self.dialog is not None: + self.dialog.destroy() + + text = ('This dialog was created by setting the Tk ' + + 'option database:\n\n *MessageDialog.buttons: ' + buttons + + '\n *MessageDialog.buttonboxpos: ' + buttonboxpos + + '\n *ButtonBox.padx: ' + pad + + '\n *ButtonBox.pady: ' + pad) + self.dialog = Pmw.MessageDialog(self.parent, + defaultbutton = 0, + title = 'Pmw option database demonstration', + message_justify = 'left', + message_text = text) + self.dialog.iconname('Test dialog') + + # Return the defaults to normal, otherwise all other demos + # will be affected. + self.parent.option_add('*MessageDialog.buttons', "('OK',)") + self.parent.option_add('*MessageDialog.buttonboxpos', 's') + self.parent.option_add('*ButtonBox.padx', 8) + self.parent.option_add('*ButtonBox.pady', 8) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root, useTkOptionDb = 1) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ScrolledCanvas.py b/Pmw/Pmw_1_2/demos/ScrolledCanvas.py new file mode 100644 index 00000000..28933ec5 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ScrolledCanvas.py @@ -0,0 +1,124 @@ +title = 'Pmw.ScrolledCanvas demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the ScrolledCanvas. + self.sc = Pmw.ScrolledCanvas(parent, + borderframe = 1, + labelpos = 'n', + label_text = 'ScrolledCanvas', + usehullsize = 1, + hull_width = 400, + hull_height = 300, + ) + + # Create a group widget to contain the scrollmode options. + w = Pmw.Group(parent, tag_text='Scroll mode') + w.pack(side = 'bottom', padx = 5, pady = 5) + + hmode = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Horizontal:', + items = ['none', 'static', 'dynamic'], + command = self.sethscrollmode, + menubutton_width = 8, + ) + hmode.pack(side = 'left', padx = 5, pady = 5) + hmode.invoke('dynamic') + + vmode = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Vertical:', + items = ['none', 'static', 'dynamic'], + command = self.setvscrollmode, + menubutton_width = 8, + ) + vmode.pack(side = 'left', padx = 5, pady = 5) + vmode.invoke('dynamic') + + buttonBox = Pmw.ButtonBox(parent) + buttonBox.pack(side = 'bottom') + buttonBox.add('yview', text = 'Show\nyview', command = self.showYView) + buttonBox.add('scroll', text = 'Page\ndown', command = self.pageDown) + buttonBox.add('center', text = 'Center', command = self.centerPage) + + # Pack this last so that the buttons do not get shrunk when + # the window is resized. + self.sc.pack(padx = 5, pady = 5, fill = 'both', expand = 1) + + self.sc.component('canvas').bind('<1>', self.addcircle) + + testEntry = Tkinter.Entry(parent) + self.sc.create_line(20, 20, 100, 100) + self.sc.create_oval(100, 100, 200, 200, fill = 'green') + self.sc.create_text(100, 20, anchor = 'nw', + text = 'Click in the canvas\nto draw ovals', + font = testEntry.cget('font')) + button = Tkinter.Button(self.sc.interior(), + text = 'Hello,\nWorld!\nThis\nis\na\nbutton.') + self.sc.create_window(200, 200, + anchor='nw', + window = button) + + # Set the scroll region of the canvas to include all the items + # just created. + self.sc.resizescrollregion() + + self.colours = ('red', 'green', 'blue', 'yellow', 'cyan', 'magenta', + 'black', 'white') + self.oval_count = 0 + self.rand = 12345 + + def sethscrollmode(self, tag): + self.sc.configure(hscrollmode = tag) + + def setvscrollmode(self, tag): + self.sc.configure(vscrollmode = tag) + + def addcircle(self, event): + x = self.sc.canvasx(event.x) + y = self.sc.canvasy(event.y) + width = 10 + self.random() % 100 + height = 10 + self.random() % 100 + self.sc.create_oval( + x - width, y - height, x + width, y + height, + fill = self.colours[self.oval_count]) + self.oval_count = (self.oval_count + 1) % len(self.colours) + self.sc.resizescrollregion() + + # Simple random number generator. + def random(self): + self.rand = (self.rand * 125) % 2796203 + return self.rand + + def showYView(self): + print self.sc.yview() + + def pageDown(self): + self.sc.yview('scroll', 1, 'page') + + def centerPage(self): + top, bottom = self.sc.yview() + size = bottom - top + middle = 0.5 - size / 2 + self.sc.yview('moveto', middle) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ScrolledField.py b/Pmw/Pmw_1_2/demos/ScrolledField.py new file mode 100644 index 00000000..b3a268df --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ScrolledField.py @@ -0,0 +1,51 @@ +title = 'Pmw.ScrolledField demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack the ScrolledField. + self._field = Pmw.ScrolledField(parent, entry_width = 30, + entry_relief='groove', labelpos = 'n', + label_text = 'Scroll the field using the\nmiddle mouse button') + self._field.pack(fill = 'x', expand = 1, padx = 10, pady = 10) + + # Create and pack a button to change the ScrolledField. + self._button = Tkinter.Button(parent, text = 'Change field', + command = self.execute) + self._button.pack(padx = 10, pady = 10) + + self._index = 0 + self.execute() + + def execute(self): + self._field.configure(text = lines[self._index % len(lines)]) + self._index = self._index + 1 + +lines = ( + 'Alice was beginning to get very tired of sitting by her sister', + 'on the bank, and of having nothing to do: once or twice she had', + 'peeped into the book her sister was reading, but it had no', + 'pictures or conversations in it, "and what is the use of a book,"', + 'thought Alice "without pictures or conversation?"', + 'Alice\'s Adventures in Wonderland', + 'Lewis Carroll', +) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ScrolledFrame.py b/Pmw/Pmw_1_2/demos/ScrolledFrame.py new file mode 100644 index 00000000..06880df1 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ScrolledFrame.py @@ -0,0 +1,157 @@ +title = 'Pmw.ScrolledFrame demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the ScrolledFrame. + self.sf = Pmw.ScrolledFrame(parent, + labelpos = 'n', label_text = 'ScrolledFrame', + usehullsize = 1, + hull_width = 400, + hull_height = 220, + ) + + # Create a group widget to contain the flex options. + w = Pmw.Group(parent, tag_text='Flex') + w.pack(side = 'bottom', padx = 5, pady = 3) + + hflex = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Horizontal:', + items = ['fixed', 'expand', 'shrink', 'elastic'], + command = self.sethflex, + menubutton_width = 8, + ) + hflex.pack(side = 'left', padx = 5, pady = 3) + hflex.invoke('fixed') + + vflex = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Vertical:', + items = ['fixed', 'expand', 'shrink', 'elastic'], + command = self.setvflex, + menubutton_width = 8, + ) + vflex.pack(side = 'left', padx = 5, pady = 3) + vflex.invoke('fixed') + + # Create a group widget to contain the scrollmode options. + w = Pmw.Group(parent, tag_text='Scroll mode') + w.pack(side = 'bottom', padx = 5, pady = 0) + + hmode = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Horizontal:', + items = ['none', 'static', 'dynamic'], + command = self.sethscrollmode, + menubutton_width = 8, + ) + hmode.pack(side = 'left', padx = 5, pady = 3) + hmode.invoke('dynamic') + + vmode = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Vertical:', + items = ['none', 'static', 'dynamic'], + command = self.setvscrollmode, + menubutton_width = 8, + ) + vmode.pack(side = 'left', padx = 5, pady = 3) + vmode.invoke('dynamic') + + self.radio = Pmw.RadioSelect(parent, selectmode = 'multiple', + command = self.radioSelected) + self.radio.add('center', text = 'Keep centered vertically') + self.radio.pack(side = 'bottom') + + buttonBox = Pmw.ButtonBox(parent) + buttonBox.pack(side = 'bottom') + buttonBox.add('add', text = 'Add a button', command = self.addButton) + buttonBox.add('yview', text = 'Show yview', command = self.showYView) + buttonBox.add('scroll', text = 'Page down', command = self.pageDown) + + # Pack this last so that the buttons do not get shrunk when + # the window is resized. + self.sf.pack(padx = 5, pady = 3, fill = 'both', expand = 1) + + self.frame = self.sf.interior() + + self.row = 0 + self.col = 0 + + for count in range(15): + self.addButton() + + def sethscrollmode(self, tag): + self.sf.configure(hscrollmode = tag) + + def setvscrollmode(self, tag): + self.sf.configure(vscrollmode = tag) + + def sethflex(self, tag): + self.sf.configure(horizflex = tag) + + def setvflex(self, tag): + self.sf.configure(vertflex = tag) + + def addButton(self): + button = Tkinter.Button(self.frame, + text = '(%d,%d)' % (self.col, self.row)) + button.grid(row = self.row, column = self.col, sticky = 'nsew') + + self.frame.grid_rowconfigure(self.row, weight = 1) + self.frame.grid_columnconfigure(self.col, weight = 1) + if self.sf.cget('horizflex') == 'expand' or \ + self.sf.cget('vertflex') == 'expand': + self.sf.reposition() + + if 'center' in self.radio.getcurselection(): + self.sf.update_idletasks() + self.centerPage() + + if self.col == self.row: + self.col = 0 + self.row = self.row + 1 + else: + self.col = self.col + 1 + + def showYView(self): + print self.sf.yview() + + def pageDown(self): + self.sf.yview('scroll', 1, 'page') + + def radioSelected(self, name, state): + if state: + self.centerPage() + + def centerPage(self): + # Example of how to use the yview() method of Pmw.ScrolledFrame. + top, bottom = self.sf.yview() + size = bottom - top + middle = 0.5 - size / 2 + self.sf.yview('moveto', middle) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + import os + if os.name == 'nt': + size = 16 + else: + size = 12 + root = Tkinter.Tk() + Pmw.initialise(root, size = size, fontScheme = 'pmw2') + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ScrolledListBox.py b/Pmw/Pmw_1_2/demos/ScrolledListBox.py new file mode 100644 index 00000000..f2f7d9d6 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ScrolledListBox.py @@ -0,0 +1,118 @@ +title = 'Pmw.ScrolledListBox demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the ScrolledListBox. + self.box = Pmw.ScrolledListBox(parent, + items=('Sydney', 'Melbourne', 'Brisbane'), + labelpos='nw', + label_text='Cities', + listbox_height = 6, + selectioncommand=self.selectionCommand, + dblclickcommand=self.defCmd, + usehullsize = 1, + hull_width = 200, + hull_height = 200, + ) + + # Create a group widget to contain the scrollmode options. + w = Pmw.Group(parent, tag_text='Scroll mode') + w.pack(side = 'bottom', padx = 5, pady = 5) + + hmode = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Horizontal:', + items = ['none', 'static', 'dynamic'], + command = self.sethscrollmode, + menubutton_width = 8, + ) + hmode.pack(side = 'top', padx = 5, pady = 5) + hmode.invoke('dynamic') + + vmode = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Vertical:', + items = ['none', 'static', 'dynamic'], + command = self.setvscrollmode, + menubutton_width = 8, + ) + vmode.pack(side = 'top', padx = 5, pady = 5) + vmode.invoke('dynamic') + + buttonBox = Pmw.ButtonBox(parent) + buttonBox.pack(side = 'bottom') + buttonBox.add('yview', text = 'Show\nyview', command = self.showYView) + buttonBox.add('scroll', text = 'Page\ndown', command = self.pageDown) + buttonBox.add('center', text = 'Center', command = self.centerPage) + + # Pack this last so that the buttons do not get shrunk when + # the window is resized. + self.box.pack(fill = 'both', expand = 1, padx = 5, pady = 5) + + # Do this after packing the scrolled list box, so that the + # window does not resize as soon as it appears (because + # alignlabels has to do an update_idletasks). + Pmw.alignlabels((hmode, vmode)) + + # Add some more entries to the listbox. + items = ('Andamooka', 'Coober Pedy', 'Innamincka', 'Oodnadatta') + self.box.setlist(items) + self.box.insert(2, 'Wagga Wagga', 'Perth', 'London') + self.box.insert('end', 'Darwin', 'Auckland', 'New York') + index = list(self.box.get(0, 'end')).index('London') + self.box.delete(index) + self.box.delete(7, 8) + self.box.insert('end', 'Bulli', 'Alice Springs', 'Woy Woy') + self.box.insert('end', 'Wallumburrawang', 'Willandra Billabong') + + def sethscrollmode(self, tag): + self.box.configure(hscrollmode = tag) + + def setvscrollmode(self, tag): + self.box.configure(vscrollmode = tag) + + def selectionCommand(self): + sels = self.box.getcurselection() + if len(sels) == 0: + print 'No selection' + else: + print 'Selection:', sels[0] + + def defCmd(self): + sels = self.box.getcurselection() + if len(sels) == 0: + print 'No selection for double click' + else: + print 'Double click:', sels[0] + + def showYView(self): + print self.box.yview() + + def pageDown(self): + self.box.yview('scroll', 1, 'page') + + def centerPage(self): + top, bottom = self.box.yview() + size = bottom - top + middle = 0.5 - size / 2 + self.box.yview('moveto', middle) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ScrolledText.py b/Pmw/Pmw_1_2/demos/ScrolledText.py new file mode 100644 index 00000000..aae02ea2 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ScrolledText.py @@ -0,0 +1,99 @@ +title = 'Pmw.ScrolledText demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import os +import math +import string +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + + # Create the ScrolledText with headers. + fixedFont = Pmw.logicalfont('Fixed') + self.st = Pmw.ScrolledText(parent, + # borderframe = 1, + labelpos = 'n', + label_text='ScrolledText with headers', + columnheader = 1, + rowheader = 1, + rowcolumnheader = 1, + usehullsize = 1, + hull_width = 400, + hull_height = 300, + text_wrap='none', + text_font = fixedFont, + Header_font = fixedFont, + Header_foreground = 'blue', + rowheader_width = 3, + rowcolumnheader_width = 3, + text_padx = 4, + text_pady = 4, + Header_padx = 4, + rowheader_pady = 4, + ) + + self.st.pack(padx = 5, pady = 5, fill = 'both', expand = 1) + + funcs = 'atan cos cosh exp log log10 sin sinh sqrt tan tanh' + funcs = string.split(funcs) + + # Create the header for the row headers + self.st.component('rowcolumnheader').insert('end', 'x') + + # Create the column headers + headerLine = '' + for column in range(len(funcs)): + headerLine = headerLine + ('%-7s ' % (funcs[column],)) + headerLine = headerLine[:-3] + self.st.component('columnheader').insert('0.0', headerLine) + + self.st.tag_configure('yellow', background = 'yellow') + + # Create the data rows and the row headers + numRows = 50 + tagList = [] + for row in range(1, numRows): + dataLine = '' + x = row / 5.0 + for column in range(len(funcs)): + value = eval('math.' + funcs[column] + '(' + str(x) + ')') + data = str(value)[:7] + if value < 0: + tag1 = '%d.%d' % (row, len(dataLine)) + tag2 = '%d.%d' % (row, len(dataLine) + len(data)) + tagList.append(tag1) + tagList.append(tag2) + data = '%-7s' % (data,) + dataLine = dataLine + data + ' ' + dataLine = dataLine[:-3] + header = '%.1f' % (x,) + if row < numRows - 1: + dataLine = dataLine + '\n' + header = header + '\n' + self.st.insert('end', dataLine) + self.st.component('rowheader').insert('end', header) + apply(self.st.tag_add, ('yellow',) + tuple(tagList)) + + # Prevent users' modifying text and headers + self.st.configure( + text_state = 'disabled', + Header_state = 'disabled', + ) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ScrolledText_2.py b/Pmw/Pmw_1_2/demos/ScrolledText_2.py new file mode 100644 index 00000000..cffb733a --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ScrolledText_2.py @@ -0,0 +1,99 @@ +title = 'Pmw.ScrolledText demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import os +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the ScrolledText. + self.st = Pmw.ScrolledText(parent, + borderframe = 1, + labelpos = 'n', + label_text='ScrolledText.py', + usehullsize = 1, + hull_width = 400, + hull_height = 300, + text_padx = 10, + text_pady = 10, + text_wrap='none' + ) + + # Create a group widget to contain the scrollmode options. + w = Pmw.Group(parent, tag_text='Scroll mode') + w.pack(side = 'bottom', padx = 5, pady = 5) + + hmode = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Horizontal:', + items = ['none', 'static', 'dynamic'], + command = self.sethscrollmode, + menubutton_width = 8, + ) + hmode.pack(side = 'left', padx = 5, pady = 5) + hmode.invoke('dynamic') + + vmode = Pmw.OptionMenu(w.interior(), + labelpos = 'w', + label_text = 'Vertical:', + items = ['none', 'static', 'dynamic'], + command = self.setvscrollmode, + menubutton_width = 8, + ) + vmode.pack(side = 'left', padx = 5, pady = 5) + vmode.invoke('dynamic') + + buttonBox = Pmw.ButtonBox(parent) + buttonBox.pack(side = 'bottom') + buttonBox.add('yview', text = 'Show\nyview', command = self.showYView) + buttonBox.add('scroll', text = 'Page\ndown', command = self.pageDown) + buttonBox.add('center', text = 'Center', command = self.centerPage) + + # Pack this last so that the buttons do not get shrunk when + # the window is resized. + self.st.pack(padx = 5, pady = 5, fill = 'both', expand = 1) + + # Read this file into the text widget. + head, tail = os.path.split(sys.argv[0]) + self.st.importfile(os.path.join(head,'ScrolledText.py')) + + self.st.insert('end', '\nThis demonstrates how to\n' + + 'add a window to a text widget: ') + counter = Pmw.Counter(self.st.component('text'), + entryfield_value = 9999) + self.st.window_create('end', window = counter) + + def sethscrollmode(self, tag): + self.st.configure(hscrollmode = tag) + + def setvscrollmode(self, tag): + self.st.configure(vscrollmode = tag) + + def showYView(self): + print self.st.yview() + + def pageDown(self): + self.st.yview('scroll', 1, 'page') + + def centerPage(self): + top, bottom = self.st.yview() + size = bottom - top + middle = 0.5 - size / 2 + self.st.yview('moveto', middle) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/SelectionDialog.py b/Pmw/Pmw_1_2/demos/SelectionDialog.py new file mode 100644 index 00000000..12fea94d --- /dev/null +++ b/Pmw/Pmw_1_2/demos/SelectionDialog.py @@ -0,0 +1,47 @@ +title = 'Pmw.SelectionDialog demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the dialog. + self.dialog = Pmw.SelectionDialog(parent, + title = 'My SelectionDialog', + buttons = ('OK', 'Cancel'), + defaultbutton = 'OK', + scrolledlist_labelpos = 'n', + label_text = 'What do you think of Pmw?', + scrolledlist_items = ('Cool man', 'Cool', 'Good', 'Bad', 'Gross'), + command = self.execute) + self.dialog.withdraw() + + # Create button to launch the dialog. + w = Tkinter.Button(parent, text = 'Show selection dialog', + command = self.dialog.activate) + w.pack(padx = 8, pady = 8) + + def execute(self, result): + sels = self.dialog.getcurselection() + if len(sels) == 0: + print 'You clicked on', result, '(no selection)' + else: + print 'You clicked on', result, sels[0] + self.dialog.deactivate(result) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/ShowBusy.py b/Pmw/Pmw_1_2/demos/ShowBusy.py new file mode 100644 index 00000000..831b7a56 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/ShowBusy.py @@ -0,0 +1,48 @@ +title = 'Blt busy cursor demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + self.parent = parent + + if Pmw.Blt.havebltbusy(parent): + text = 'Click here to show the\nbusy cursor for one second.' + else: + text = 'Sorry\n' \ + 'Either the BLT package has not\n' \ + 'been installed on this system or\n' \ + 'it does not support the busy command.\n' \ + 'Clicking on this button will pause\n' \ + 'for one second but will not display\n' \ + 'the busy cursor.' + + button = Tkinter.Button(parent, + text = text, + command = Pmw.busycallback(self.sleep, parent.update)) + button.pack(padx = 10, pady = 10) + + entry = Tkinter.Entry(parent, width = 30) + entry.insert('end', 'Try to enter some text while busy.') + entry.pack(padx = 10, pady = 10) + + def sleep(self): + self.parent.after(1000) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/SpecialCounter.py b/Pmw/Pmw_1_2/demos/SpecialCounter.py new file mode 100644 index 00000000..a76645a1 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/SpecialCounter.py @@ -0,0 +1,68 @@ +title = 'Subclassing Pmw.Counter' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import time +import types +import Tkinter +import Pmw + +class LabeledDateCounter(Pmw.Counter): + + def __init__(self, parent=None , **kw): + + # Need to use long ints here because on the Macintosh the maximum size + # of an integer is smaller than the value returned by time.time(). + now = (long(time.time()) / 300) * 300 + text = time.strftime('%y/%m/%d', time.localtime(now)) + + kw['datatype'] = 'date' + kw['entryfield_validate'] = 'date' + kw['entryfield_value'] = text + kw['labelpos'] = 'w' + + apply(Pmw.Counter.__init__, (self, parent), kw) + +class LabeledRealCounter(Pmw.Counter): + + def __init__(self, parent=None , **kw): + + # Define the validate option dictionary. + validate = {'validator' : 'real', 'min' : 0.0, 'max' : 100.0} + + kw['datatype'] = 'real' + kw['entryfield_validate'] = validate + kw['entryfield_value'] = 50.0 + kw['labelpos'] = 'w' + + apply(Pmw.Counter.__init__, (self, parent), kw) + +class Demo: + def __init__(self, parent): + # Create and pack some LabeledDateCounters and LabeledRealCounter. + self._date1 = LabeledDateCounter(parent, label_text = 'Date:') + self._date2 = LabeledDateCounter(parent, label_text = 'Another Date:') + self._real1 = LabeledRealCounter(parent, label_text = 'Real:') + self._real2 = LabeledRealCounter(parent, label_text = 'Another Real:') + + counters = (self._date1, self._date2, self._real1, self._real2) + + for counter in counters: + counter.pack(fill='x', expand=1, padx=10, pady=5) + Pmw.alignlabels(counters) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/SpecialEntry.py b/Pmw/Pmw_1_2/demos/SpecialEntry.py new file mode 100644 index 00000000..270780b5 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/SpecialEntry.py @@ -0,0 +1,170 @@ +title = 'Subclassing Pmw.EntryField' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import time +import types +import Tkinter +import Pmw + +class SpecialEntry(Pmw.EntryField): + + def __init__(self, parent=None , **kw): + + kw['extravalidators'] = _myValidators + apply(Pmw.EntryField.__init__, (self, parent), kw) + self._converter = None + + def setentry(self, text): + # Override Pmw.EntryField.setentry to pass string through + # the appropriate converter. + + val = self['validate'] + if type(val) == types.DictionaryType: + val = val['validator'] + if _converters.has_key(val): + text = _converters[val](text, output = 0) + Pmw.EntryField.setentry(self, text) + + def getentry(self): + text = self.get() + val = self['validate'] + if type(val) == types.DictionaryType: + val = val['validator'] + if _converters.has_key(val): + return _converters[val](text, output = 1) + else: + return text + +def _date(text): + return Pmw.datevalidator(text, 'dmy', '.') + +def _real(text): + return Pmw.realvalidator(text, ',') + +def _dateconv(text, output = 0): + # On output, convert from dd.mm.yy to mm-dd-yy. On input, convert + # mm-dd-yy to dd.mm.yy and also from +NN+ or -NN- to date NN days + # before or after today. + + if len(text) == 0: + return '' + if output: + try: + d = string.split(text, '.') + return d[1] + '-' + d[0] + '-' + d[2] + except: + return text + else: + if text[-1] == '+' or text[-1] == '-': + text = text[:-1] + if text[0] == '+' or text[0] == '-': + secondsAhead = string.atoi(text) * 3600 * 24 + return time.strftime('%d.%m.%Y', + time.localtime(time.time() + secondsAhead)) + try: + d = string.split(text,'-') + return d[1] + '.' + d[0] + '.' + d[2] + except: + return text + +def _realconv(text, output = 0): + # Convert between DD.DD and DD,DD. + + if output: + index = string.find(text, ',') + if index >= 0: + return text[:index] + '.' + text[index + 1:] + else: + return text + else: + index = string.find(text, '.') + if index >= 0: + return text[:index] + ',' + text[index + 1:] + else: + return text + + +_converters = { + 'real' : _realconv, + 'float8' : _realconv, + 'date' : _dateconv +} + +_myValidators = { + 'date' : (_date, lambda s: Pmw.datestringtojdn(s, 'dmy', '.')), + 'real' : (_real, lambda s: string.atof(_realconv(s, 1))), + 'int4' : ('numeric', 'numeric'), + 'oid' : ('int4', 'int4'), + 'float8' : ('real', 'real'), + 'varchar' : ('alphanumeric', 'alphanumeric'), + 'text' : ('alphanumeric', 'alphanumeric'), +} + +class Demo: + def __init__(self, parent): + # Create and pack the SpecialEntry megawidgets. + self._any = SpecialEntry(parent, + labelpos = 'w', + label_text = 'Text (max 10 chars):', + validate = {'validator' : 'text', 'max' : 10}, + command = self.execute) + self._any.setentry('abc') + self._int = SpecialEntry(parent, + labelpos = 'w', + label_text = 'Int4:', + validate = 'int4') + self._int.setentry(1) + self._real = SpecialEntry(parent, + labelpos = 'w', + label_text = 'Real (max 2,5e+9):', + validate = {'validator' : 'real', 'max' : +2.5e+9}, + ) + self._real.setentry('+2.5e+6') + self._date = SpecialEntry(parent, + labelpos = 'w', + label_text = 'Date (dd.mm.yy):', + validate = 'date', + modifiedcommand = self.changed + ) + # Set entry to one week from now, using special intput format. + self._date.setentry('+7+') + + entries = (self._any, self._int, self._real, self._date) + + for entry in entries: + entry.pack(fill='x', expand=1, padx=10, pady=5) + Pmw.alignlabels(entries) + + self._any.component('entry').focus_set() + + def changed(self): + print 'Text changed, converted value is', self._date.getentry() + + def execute(self): + print 'Return pressed, value is', self._any.get() + + # This implements a custom validation routine. It simply checks + # if the string is of odd length. + def custom_validate(self, text): + print 'text:', text + if len(text) % 2 == 0: + return -1 + else: + return 1 + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/Spectrum.py b/Pmw/Pmw_1_2/demos/Spectrum.py new file mode 100644 index 00000000..cfef9791 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/Spectrum.py @@ -0,0 +1,166 @@ +title = 'Color spectrum demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + parent = Tkinter.Frame(parent) + parent.pack(padx=10, pady=10, fill='both', expand=1) + self.width = 350 + self.height = 250 + self.canvas = Tkinter.Canvas(parent, + width = self.width, height = self.height) + self.canvas.grid(row = 0, column = 0, columnspan = 2, sticky = 'news') + + self.numColors = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Number of colors:', + entry_width = 5, + validate = 'numeric', + command = Pmw.busycallback(self.execute)) + self.numColors.grid(row = 1, column = 0, sticky = 'ew') + + self.correction = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Correction:', + validate = 'real', + entry_width = 5, + command = Pmw.busycallback(self.execute)) + self.correction.grid(row = 1, column = 1, sticky = 'ew') + + self.saturation = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Saturation:', + validate = 'real', + entry_width = 5, + command = Pmw.busycallback(self.execute)) + self.saturation.grid(row = 2, column = 0, sticky = 'ew') + + self.intensity = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Intensity:', + validate = 'real', + entry_width = 5, + command = Pmw.busycallback(self.execute)) + self.intensity.grid(row = 2, column = 1, sticky = 'ew') + + self.extraOrange = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Emphasize orange (0 or 1):', + validate = {'validator' : 'numeric', 'min' : 0, 'max' : 1}, + entry_width = 5, + command = Pmw.busycallback(self.execute)) + self.extraOrange.grid(row = 3, column = 0, sticky = 'ew') + + self.text = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Text:', + entry_width = 20, + command = Pmw.busycallback(self.execute)) + self.text.grid(row = 4, column = 0, sticky = 'ew') + + self.brightness = Pmw.EntryField(parent, + labelpos = 'w', + label_text = 'Brightness:', + validate = 'real', + entry_width = 5, + command = Pmw.busycallback(self.execute)) + self.brightness.grid(row = 3, column = 1, sticky = 'ew') + + self.radiobuttons = Pmw.RadioSelect(parent, + command = Pmw.busycallback(self.radio_cb), + ) + self.radiobuttons.grid(row = 4, column = 1) + self.radiobuttons.add('Use saturation\nand intensity') + self.radiobuttons.add('Use\nbrightness') + + parent.grid_columnconfigure(0, weight = 1) + parent.grid_columnconfigure(1, weight = 1) + parent.grid_rowconfigure(0, weight = 1) + + Pmw.alignlabels((self.numColors, self.saturation, self.extraOrange)) + Pmw.alignlabels((self.correction, self.intensity, self.brightness)) + + # Set initial values for all entries. + self.numColors.setentry('64') + self.correction.setentry('1.0') + self.saturation.setentry('1.0') + self.intensity.setentry('1.0') + self.extraOrange.setentry('1') + self.brightness.setentry('0.7') + self.text.setentry('This is a test') + self.radiobuttons.invoke('Use saturation\nand intensity') + + self.execute() + + def radio_cb(self, value): + self.execute() + + def execute(self): + try: + numColors = string.atoi(self.numColors.get()) + correction = string.atof(self.correction.get()) + saturation = string.atof(self.saturation.get()) + intensity = string.atof(self.intensity.get()) + extraOrange = string.atof(self.extraOrange.get()) + brightness = string.atof(self.brightness.get()) + except ValueError: + self.numColors.bell() + return + + if numColors <= 0: + self.numColors.bell() + return + + self.canvas.delete('all') + + colorList = Pmw.Color.spectrum( + numColors, correction, saturation, intensity, extraOrange) + extent = 360.0 / numColors + + useBrightness = \ + (self.radiobuttons.getcurselection() == 'Use\nbrightness') + + if numColors == 1: + # Special case circle, since create_arc does not work when + # extent is 360. + background = colorList[0] + if useBrightness: + background = Pmw.Color.changebrightness( + self.canvas, background, brightness) + self.canvas.create_oval(10, 10, self.width - 10, self.height - 10, + fill = background, outline = background) + + for index in range(numColors): + start = index * extent - extent / 2 + background = colorList[index] + if useBrightness: + background = Pmw.Color.changebrightness( + self.canvas, background, brightness) + self.canvas.create_arc(10, 10, self.width - 10, self.height - 10, + start = start, extent = extent, + fill = background, outline = background) + + text = self.text.get() + self.canvas.create_text(self.width / 2, self.height / 3, text = text) + self.canvas.create_text(self.width / 2, self.height / 2, text = text) + self.canvas.create_text(self.width / 2, 2 * self.height / 3, text = text) + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/SpeedTest.py b/Pmw/Pmw_1_2/demos/SpeedTest.py new file mode 100644 index 00000000..589486bb --- /dev/null +++ b/Pmw/Pmw_1_2/demos/SpeedTest.py @@ -0,0 +1,60 @@ +title = 'Test of the speed of creating Pmw megawidgets' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import time +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + self.parent = parent + + message = 'This is a test of the time\n' + \ + 'it takes to create 20 Pmw\nEntryField megawidgets.\n' + \ + 'Click on the button to create them.' + w = Tkinter.Label(parent, text = message) + w.pack(padx = 8, pady = 8) + + # Create button to run speed test. + w = Tkinter.Button(parent, + text = 'Create 20 EntryFields', + command = self.createEntries) + w.pack(padx = 8, pady = 8) + + def createEntries(self): + entryTop = Tkinter.Toplevel(self.parent) + + startClock = time.clock() + fields = [] + for num in range(20): + field = Pmw.EntryField(entryTop, + labelpos = 'w', + label_text='*' + ('*' * num), + hull_background = 'lightsteelblue', + label_background = 'lightsteelblue', + hull_highlightbackground = 'lightsteelblue', + label_highlightbackground = 'lightsteelblue', + entry_highlightbackground = 'lightsteelblue', + entry_background = 'aliceblue') + field.pack() + fields.append(field) + + Pmw.alignlabels(fields) + print 'Time to create 20 EntryFields:', \ + time.clock() - startClock, 'seconds' + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/SubClassing.py b/Pmw/Pmw_1_2/demos/SubClassing.py new file mode 100644 index 00000000..f538b59e --- /dev/null +++ b/Pmw/Pmw_1_2/demos/SubClassing.py @@ -0,0 +1,128 @@ +title = 'More examples of subclassing' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class ExtraMethods(Pmw.EntryField): + + # How to subclass a Pmw megawidget when you only want to add or + # override methods. + + def doubletext(self): + self.setvalue(self.getvalue() + ' ' + self.getvalue()) + +class OverrideInit(Pmw.EntryField): + + # How to subclass a Pmw megawidget when you want to define + # a new __init__ method. + + def __init__(self, textToAdd, parent = None, **kw): + self._textToAdd = textToAdd + apply(Pmw.EntryField.__init__, (self, parent), kw) + + def addtext(self): + self.setvalue(self.getvalue() + ' ' + self._textToAdd) + +class DefaultOptions(Pmw.EntryField): + + # How to subclass a Pmw megawidget when you only want to set + # existing options to new default values. + + def __init__(self, parent = None, **kw): + kw['label_foreground'] = 'blue' + kw['entry_background'] = 'white' + apply(Pmw.EntryField.__init__, (self, parent), kw) + +class NewOptions(Pmw.EntryField): + + # How to subclass a Pmw megawidget when you want to add new options. + + def __init__(self, parent=None , **kw): + + # Define the megawidget options. + optiondefs = ( + ('backgrounds', None, self._backgrounds), + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.EntryField.__init__(self, parent) + + # Check keywords and initialise options. + self.initialiseoptions() + + def _backgrounds(self): + background = self['backgrounds'] + Pmw.Color.changecolor(self.component('hull'), background) + +class Demo: + def __init__(self, parent): + # Create and pack the megawidgets. + self._extraMethod = ExtraMethods(parent, + labelpos = 'w', + label_text = 'Sub class with extra method:', + value = 'Hello' + ) + self._overrideInit = OverrideInit('Again', parent, + labelpos = 'w', + label_text = 'Sub class with new __init__ method:', + value = 'Hello' + ) + self._defaultOptions = DefaultOptions(parent, + labelpos = 'w', + label_text = 'Sub class with new default options:', + value = 'Hello' + ) + + self._newOptions = NewOptions(parent, + labelpos = 'w', + label_text = 'Sub class with new option:', + value = 'Hello', + backgrounds = 'white', + ) + + entries = (self._extraMethod, self._overrideInit, + self._defaultOptions, self._newOptions) + + for entry in entries: + entry.pack(fill='x', expand=1, padx=10, pady=5) + Pmw.alignlabels(entries) + + bb = Pmw.ButtonBox(parent) + bb.add('Double text', command = self._doubleText) + bb.pack() + bb.add('Add text', command = self._addText) + bb.pack() + bb.add('White', command = self._changeColorWhite) + bb.pack() + bb.add('Green', command = self._changeColorGreen) + bb.pack() + + def _doubleText(self): + self._extraMethod.doubletext() + + def _addText(self): + self._overrideInit.addtext() + + def _changeColorWhite(self): + self._newOptions.configure(backgrounds = 'white') + + def _changeColorGreen(self): + self._newOptions.configure(backgrounds = 'green') + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/TextDialog.py b/Pmw/Pmw_1_2/demos/TextDialog.py new file mode 100644 index 00000000..adec8214 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/TextDialog.py @@ -0,0 +1,75 @@ +title = 'Pmw.TextDialog demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create the dialog. + dialog = Pmw.TextDialog(parent, scrolledtext_labelpos = 'n', + title = 'My TextDialog', + defaultbutton = 0, + label_text = 'Lawyer jokes') + dialog.withdraw() + dialog.insert('end', jokes) + dialog.configure(text_state = 'disabled') + + # Create button to launch the dialog. + w = Tkinter.Button(parent, text = 'Show text dialog', + command = dialog.activate) + w.pack(padx = 8, pady = 8) + +jokes = """ +Q: What do you call 5000 dead lawyers at the bottom of the ocean? +A: A good start! + +Q: How can you tell when a lawyer is lying? +A: His lips are moving. + +Q: Why won't sharks attack lawyers? +A: Professional courtesy. + +Q: What do have when a lawyer is buried up to his neck in sand? +A: Not enough sand. + +Q: How do you get a lawyer out of a tree? +A: Cut the rope. + +Q: What is the definition of a shame (as in "that's a shame")? +A: When a bus load of lawyers goes off a cliff. + +Q: What is the definition of a "crying shame"? +A: There was an empty seat. + +Q: What do you get when you cross the Godfather with a lawyer? +A: An offer you can't understand. + +Q. What do lawyers use as contraceptives? +A. Their personalities. + +Q. What's brown and black and looks good on a lawyer? +A. A doberman. + +Q. Why are lawyers buried 12 feet underground? +A. Deep down their good. + +Q. What's the difference between a catfish and a lawyer? +A. One's a slimy scum-sucking scavenger, the other is just a fish. + +""" +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/TextDisplay.py b/Pmw/Pmw_1_2/demos/TextDisplay.py new file mode 100644 index 00000000..0eadf525 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/TextDisplay.py @@ -0,0 +1,78 @@ +title = 'Demonstration of how to create a megawidget' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class TextDisplay(Pmw.MegaWidget): + + # Demo Pmw megawidget. + + def __init__(self, parent = None, **kw): + + # Define the megawidget options. + optiondefs = () + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaWidget.__init__(self, parent) + + # Create the components. + interior = self.interior() + + self._text = self.createcomponent('text', + (), None, + Tkinter.Text, (interior,), state = 'disabled') + self._text.pack(side='left', fill='both', expand='yes') + + self._scrollbar = self.createcomponent('scrollbar', + (), None, + Tkinter.Scrollbar, (interior,), command = self._text.yview) + self._scrollbar.pack(side='right', fill='y') + self._text.configure(yscrollcommand = self._scrollbar.set) + + # Check keywords and initialise options. + self.initialiseoptions() + + def display(self, info): + self._text.configure(state = 'normal') + self._text.delete('1.0', 'end') + self._text.insert('1.0', info) + self._text.configure(state = 'disabled') + + def append(self, info): + self._text.configure(state = 'normal') + self._text.insert('end', info) + self._text.configure(state = 'disabled') + +class Demo: + def __init__(self, parent): + # Create and pack the megawidget. + text = TextDisplay(parent, + text_background = 'aliceblue', + text_width = 40, + text_height = 10, + text_wrap = 'none', + ) + text.pack(fill = 'both', expand = 1) + text.display('This is an example of a simple Pmw megawidget.\n\n' + + 'Public attributes of the Tkinter module:\n\n') + for name in dir(Tkinter): + if name[0] != '_': + text.append(' ' + name + '\n') + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/TimeCounter.py b/Pmw/Pmw_1_2/demos/TimeCounter.py new file mode 100644 index 00000000..7be1eb36 --- /dev/null +++ b/Pmw/Pmw_1_2/demos/TimeCounter.py @@ -0,0 +1,40 @@ +title = 'Pmw.TimeCounter demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import string +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + self._time = Pmw.TimeCounter(parent, + labelpos = 'w', + label_text = 'HH:MM:SS', + min = '00:00:00', + max = '23:59:59') + self._time.pack(padx=10, pady=5) + + button = Tkinter.Button(parent, text = 'Show', command = self.show) + button.pack() + + def show(self): + stringVal = self._time.getstring() + intVal = self._time.getint() + print stringVal + ' (' + str(intVal) + ')' + + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/demos/WidgetDestroy.py b/Pmw/Pmw_1_2/demos/WidgetDestroy.py new file mode 100644 index 00000000..a62fa28c --- /dev/null +++ b/Pmw/Pmw_1_2/demos/WidgetDestroy.py @@ -0,0 +1,36 @@ +title = 'Demonstration of Pmw megawidget destruction' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + # Create and pack an EntryField. + self.entryfield = Pmw.EntryField(parent, + command = self.execute, + value = 'Press to destroy me', + entry_width = 30) + self.entryfield.pack(fill='x', expand=1, padx=10, pady=5) + + self.entryfield.component('entry').focus_set() + + def execute(self): + print 'Return pressed, destroying EntryField.' + self.entryfield.destroy() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/doc/AboutDialog.gif b/Pmw/Pmw_1_2/doc/AboutDialog.gif new file mode 100644 index 00000000..2d60dc59 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/AboutDialog.gif differ diff --git a/Pmw/Pmw_1_2/doc/AboutDialog.html b/Pmw/Pmw_1_2/doc/AboutDialog.html new file mode 100644 index 00000000..8f487d5b --- /dev/null +++ b/Pmw/Pmw_1_2/doc/AboutDialog.html @@ -0,0 +1,286 @@ + + + + + + Pmw.AboutDialog reference manual + + + + +

Pmw.AboutDialog

+ +
+
+

Name

+

Pmw.AboutDialog() - + window to display version and contact information +

+ + +
+

Inherits

+Pmw.MessageDialog
+
+

Description

+

+ An about dialog is a dialog window which displays information + about the application, such as name, version, copyright and + contact details.

+ +

The text of the message is constructed from the application name + (given by the applicationname option) followed by the values + supplied in the most recent calls to Pmw.aboutversion(), + Pmw.aboutcopyright() and Pmw.aboutcontact() functions.

+ +

The icon of the message defaults to 'info', but may be changed + using the icon_bitmap component option.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
applicationname +
+Initialisation option. The name of application, to be dispayed in the dialog body and in + the window title if the title option is not given. The default is ''.

+ + +
+ +
borderx +
+Initialisation option. The padding to the left and right of the text message and icon. The default is 20.

+ + +
+ +
bordery +
+Initialisation option. The padding above and below the text message and icon. The default is 20.

+ + +
+ +
buttonboxpos +
+Initialisation option. Specifies on which side of the dialog window to place the button + box. Must be one of 'n', 's', 'e' or 'w'. The default is 's'.

+ + +
+ +
buttons +
+This must be a tuple or a list and specifies the names on the + buttons in the button box. The default is ('Close',).

+ + +
+ +
command +
+Specifies a function to call whenever a button in the button box + is invoked or the window is deleted by the window manager. The + function is called with a single argument, which is the name of + the button which was invoked, or None if the window was deleted + by the window manager.

+

If the value of command is not callable, the default behaviour + is to deactivate the window if it is active, or withdraw the + window if it is not active. If it is deactivated, deactivate() + is called with the button name or None as described above. The default is None.

+ + + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
defaultbutton +
+Specifies the default button in the button box. If the <Return> + key is hit when the dialog has focus, the default button will be + invoked. If defaultbutton is None, there will be no default + button and hitting the <Return> key will have no effect. The default is 0.

+ + +
+ +
iconmargin +
+Initialisation option. The padding between the text message and icon. The default is 20.

+ + +
+ +
iconpos +
+Initialisation option. Specifies on which side of the text message to place the icon. + Must be one of 'n', 's', 'e' or 'w'. The default is 'w'.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
separatorwidth +
+Initialisation option. If this is greater than 0, a separator line with the specified + width will be created between the button box and the child site, + as a component named separator. Since the default border of the + button box and child site is raised, this option does not + usually need to be set for there to be a visual separation between + the button box and child site. The default is 0.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
buttonbox +
+This is the button box containing the buttons for the dialog. By + default it is created with the options + (hull_borderwidth = 1, hull_relief = 'raised'). By default, this component is a Pmw.ButtonBox.

+ + +
+ +
dialogchildsite +
+This is the child site for the dialog, which may be used to + specialise the megawidget by creating other widgets within it. By + default it is created with the options + (borderwidth = 1, relief = 'raised'). By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
icon +
+If the iconpos option is not None, this component is created + to contain the icon label for the dialog. To display a bitmap as + an icon, set the icon_bitmap component option to any of the + forms acceptable to Tk, such as 'warning' or 'error'. By default, this component is a Tkinter.Label.

+ + +
+ +
message +
+The label to contain the text message for the dialog. To set + the text, use the message_text component option. By default, this component is a Tkinter.Label.

+ + +
+ +
separator +
+If the separatorwidth initialisation option is non-zero, the + separator component is the line dividing the area between the + button box and the child site. By default, this component is a Tkinter.Frame.

+ + +
+
+ +

Methods

+This megawidget has no methods of its own. +For a description of its inherited methods, see the +manual for its base class +Pmw.MessageDialog. +

+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create dialog.
+        Pmw.aboutversion('9.9')
+        Pmw.aboutcopyright('Copyright My Company 1999\nAll rights reserved')
+        Pmw.aboutcontact(
+            'For information about this application contact:\n' +
+            '  My Help Desk\n' +
+            '  Phone: +61 2 9876 5432\n' +
+            '  email: help@my.company.com.au'
+        )
+        self.about = Pmw.AboutDialog(parent, applicationname = 'My Application')
+        self.about.withdraw()
+
+        # Create button to launch the dialog.
+        w = Tkinter.Button(parent, text = 'Show about dialog',
+                command = self.execute)
+        w.pack(padx = 8, pady = 8)
+
+    def execute(self):
+        self.about.show()
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/Balloon.gif b/Pmw/Pmw_1_2/doc/Balloon.gif new file mode 100644 index 00000000..e8bc9b81 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/Balloon.gif differ diff --git a/Pmw/Pmw_1_2/doc/Balloon.html b/Pmw/Pmw_1_2/doc/Balloon.html new file mode 100644 index 00000000..012f9c39 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/Balloon.html @@ -0,0 +1,429 @@ + + + + + + Pmw.Balloon reference manual + + + + +

Pmw.Balloon

+ +
+
+

Name

+

Pmw.Balloon() - + display "tool tips" for a number of widgets +

+ + +
+

Inherits

+Pmw.MegaToplevel
+
+

Description

+

+ A balloon megawidget can be used to give short help messages to + the user when they place the mouse over a button or other widget + for a short time. It can also be used to display help messages + for canvas or text items.

+ +

One balloon megawidget can be used to display help for many + widgets or items. For each widget or item that requires balloon + help, the bind() or bindtag() method is used to specify the + help text that should be displayed.

+ +

The help message is displayed in a popup balloon window when the + mouse remains over the widget or item for a short time. The popup + balloon is withdrawn when the mouse leaves the widget or item, or + any mouse buttons are pressed.

+ +

The position of the popup balloon is configurable and may appear + either relative to the widget or item or relative to the position + of the mouse.

+ +

The popup balloon is displayed without any window manager + decorations.

+ +

The megawidget can cooperate with a Pmw.MessageBar to display a + single-line help message as well as the balloon help.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
initwait +
+The number of milliseconds delay between when the mouse enters a + widget or item and when the popup balloon window should be + displayed. The default is 500.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
relmouse +
+This may be one of 'both', 'x', 'y' or 'none' and + indicates that the top left corner of the popup balloon window + should be placed relative to the current position of the mouse + rather than relative to the bottom left corner of the widget or + item (the default). The positioning may be set for the horizontal + (x) and vertical (y) axes independently. The default is 'none'.

+ + +
+ +
state +
+This may be one of 'both', 'balloon', 'status' or 'none' + and indicates whether the help message should be displayed in the + popup balloon window, in an associated messagebar (via the + statuscommand option), or both. The default is 'both'.

+ + +
+ +
statuscommand +
+This specifies a function to call when the mouse enters a widget + or item bound to this balloon megawidget. To configure a + Pmw.MessageBar to display help, set this option to the helpmessage + method of the messagebar. The default is None.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+ +
xoffset +
+This specifies the horizontal offset of the position of the left + side of the popup balloon window relative the point determined by + the relmouse option. The default is 20.

+ + +
+ +
yoffset +
+This specifies the vertical offset of the position of the top of + the popup balloon window relative the point determined by the + relmouse option. The default is 1.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
label +
+This component displays the text of the help message in the popup + balloon window. By default it is created with a 'lightyellow' + background, a 'black' foreground and is 'left' justified. By default, this component is a Tkinter.Label.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaToplevel. +

+ +
bind(widget, balloonHelp, statusHelp = None)
+Create bindings for widget so that balloon help and/or status + help is displayed when the mouse enters the widget. The balloon + help message is given by balloonHelp and the status help message + is given by statusHelp. If balloonHelp is None, no balloon + is displayed. If statusHelp is not set, it defaults to + balloonHelp. Any previous bindings for this widget are removed.

+ + +
+ +
clearstatus()
+Clear the text in the associated messagebar by passing None to + the statuscommand function.

+ + +
+ +
showstatus(statusHelp)
+Set the text in the associated messagebar by passing statusHelp + to the statuscommand function.

+ + +
+ +
tagbind(widget, tagOrItem, balloonHelp, statusHelp = None)
+Create bindings for the tag or item specified by tagOrItem in + the text or canvas widget so that balloon help and/or status + help is displayed when the mouse enters the tag or item. The + balloon help message is given by balloonHelp and the status help + message is given by statusHelp. If balloonHelp is None, no + balloon is displayed. If statusHelp is not set, it defaults to + balloonHelp. Any previous bindings for this tag or item are + removed.

+ + +
+ +
tagunbind(widget, tagOrItem)
+Remove the balloon help bindings from the tag or item specified by + tagOrItem in the text or canvas widget.

+

Note that tagunbind() must be called when deleting a canvas + item, so that the popup balloon window can be withdrawn if it was + triggered by the item. (Unfortunately this can not be automated + as is done for widgets since Tk does not support <Destroy> + bindings on canvas items, so there is no way that Pmw.Balloon can + be notified of the deletion of an item.)

+ + + +
+ +
unbind(widget)
+Remove the balloon help bindings from widget.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the Balloon.
+        self.balloon = Pmw.Balloon(parent)
+
+        # Create some widgets and megawidgets with balloon help.
+        frame = Tkinter.Frame(parent)
+        frame.pack(padx = 10, pady = 5)
+        field = Pmw.EntryField(frame,
+                labelpos = 'nw',
+                label_text = 'Command:')
+        field.setentry('mycommand -name foo')
+        field.pack(side = 'left', padx = 10)
+        self.balloon.bind(field, 'Command to\nstart/stop',
+                'Enter the shell command to control')
+
+        start = Tkinter.Button(frame, text='Start')
+        start.pack(side='left', padx = 10)
+        self.balloon.bind(start, 'Start the command')
+
+        stop = Tkinter.Button(frame, text='Stop')
+        stop.pack(side='left', padx = 10)
+        self.balloon.bind(stop, 'Stop the command')
+
+        self.suicide = Tkinter.Button(frame, text='Kill me soon!',
+            command = self.killButton)
+        self.suicide.pack(side='left', padx = 10)
+        self.balloon.bind(self.suicide, 'Watch this button disappear!')
+
+        scrolledCanvas = Pmw.ScrolledCanvas(parent,
+                canvas_width = 300,
+                canvas_height = 115,
+        )
+        scrolledCanvas.pack()
+        canvas = scrolledCanvas.component('canvas')
+        self.canvas = canvas
+
+        # Create some canvas items and individual help.
+        item = canvas.create_arc(5, 5, 35, 35, fill = 'red', extent = 315)
+        self.balloon.tagbind(canvas, item, 'This is help for\nan arc item')
+        item = canvas.create_bitmap(20, 150, bitmap = 'question')
+        self.balloon.tagbind(canvas, item, 'This is help for\na bitmap')
+        item = canvas.create_line(50, 60, 70, 80, 85, 20, width = 5)
+        self.balloon.tagbind(canvas, item, 'This is help for\na line item')
+        item = canvas.create_text(10, 90, text = 'Canvas items with balloons',
+                anchor = 'nw', font = field.cget('entry_font'))
+        self.balloon.tagbind(canvas, item, 'This is help for\na text item')
+
+        # Create two canvas items which have the same tag and which use
+        # the same help.
+        canvas.create_rectangle(100, 10, 170, 50, fill = 'aliceblue',
+                tags = 'TAG1')
+        self.bluecircle = canvas.create_oval(110, 30, 160, 80, fill = 'blue',
+                tags = 'TAG1')
+        self.balloon.tagbind(canvas, 'TAG1',
+                'This is help for the two blue items' + '\n' * 10 +
+                    'It is very, very big.',
+                'This is help for the two blue items')
+        item = canvas.create_text(180, 10, text = 'Delete',
+                anchor = 'nw', font = field.cget('entry_font'))
+        self.balloon.tagbind(canvas, item,
+                'After 2 seconds,\ndelete the blue circle')
+        canvas.tag_bind(item, '<ButtonPress>', self._canvasButtonpress)
+        scrolledCanvas.resizescrollregion()
+
+        scrolledText = Pmw.ScrolledText(parent,
+                text_width = 32,
+                text_height = 4,
+                text_wrap = 'none',
+        )
+        scrolledText.pack(pady = 5)
+        text = scrolledText.component('text')
+        self.text = text
+
+        text.insert('end',
+                'This is a text widget with ', '',
+                ' balloon', 'TAG1',
+                '\nhelp. Find the ', '',
+                ' text ', 'TAG1',
+                ' tagged with', '',
+                ' help.', 'TAG2',
+                '\n', '',
+                'Remove tag 1.', 'TAG3',
+                '\nAnother line.\nAnd another', '',
+        )
+        text.tag_configure('TAG1', borderwidth = 2, relief = 'sunken')
+        text.tag_configure('TAG3', borderwidth = 2, relief = 'raised')
+
+        self.balloon.tagbind(text, 'TAG1',
+                'There is one secret\nballoon help.\nCan you find it?')
+        self.balloon.tagbind(text, 'TAG2',
+                'Well done!\nYou found it!')
+        self.balloon.tagbind(text, 'TAG3',
+                'After 2 seconds\ndelete the tag')
+        text.tag_bind('TAG3', '<ButtonPress>', self._textButtonpress)
+
+        frame = Tkinter.Frame(parent)
+        frame.pack(padx = 10)
+        self.toggleBalloonVar = Tkinter.IntVar()
+        self.toggleBalloonVar.set(1)
+        toggle = Tkinter.Checkbutton(frame,
+                variable = self.toggleBalloonVar,
+                text = 'Balloon help', command = self.toggle)
+        toggle.pack(side = 'left', padx = 10)
+        self.balloon.bind(toggle, 'Toggle balloon help\non and off')
+
+        self.toggleStatusVar = Tkinter.IntVar()
+        self.toggleStatusVar.set(1)
+        toggle = Tkinter.Checkbutton(frame,
+                variable = self.toggleStatusVar,
+                text = 'Status help', command = self.toggle)
+        toggle.pack(side = 'left', padx = 10)
+        self.balloon.bind(toggle,
+                'Toggle status help on and off, on and off' + '\n' * 10 +
+                    'It is very, very big, too.',
+                'Toggle status help on and off')
+
+        # Create and pack the MessageBar.
+        messageBar = Pmw.MessageBar(parent,
+                entry_width = 40,
+                entry_relief='groove',
+                labelpos = 'w',
+                label_text = 'Status:')
+        messageBar.pack(fill = 'x', expand = 1, padx = 10, pady = 5)
+
+        # Configure the balloon to display its status messages in the
+        # message bar.
+        self.balloon.configure(statuscommand = messageBar.helpmessage)
+
+    def toggle(self):
+        if self.toggleBalloonVar.get():
+            if self.toggleStatusVar.get():
+                self.balloon.configure(state = 'both')
+            else:
+                self.balloon.configure(state = 'balloon')
+        else:
+            if self.toggleStatusVar.get():
+                self.balloon.configure(state = 'status')
+            else:
+                self.balloon.configure(state = 'none')
+
+    def killButton(self):
+        # Test for old bug when destroying widgets 1) while the
+        # balloon was up and 2) during the initwait period.
+        print 'Destroying button in 2 seconds'
+        self.suicide.after(2000, self.suicide.destroy)
+
+    def _canvasButtonpress(self, event):
+        print 'Destroying blue circle in 2 seconds'
+        self.canvas.after(2000, self.deleteBlueCircle)
+
+    def deleteBlueCircle(self):
+        self.balloon.tagunbind(self.canvas, self.bluecircle)
+        self.canvas.delete(self.bluecircle)
+
+    def _textButtonpress(self, event):
+        print 'Deleting the text tag in 2 seconds'
+        self.text.after(2000, self.deleteTextTag)
+
+    def deleteTextTag(self):
+        self.balloon.tagunbind(self.text, 'TAG1')
+        self.text.tag_delete('TAG1')
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 20 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/Blt.html b/Pmw/Pmw_1_2/doc/Blt.html new file mode 100644 index 00000000..99869840 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/Blt.html @@ -0,0 +1,135 @@ + + + + + + Pmw.Blt reference manual + + + + +

Pmw.Blt

+ +
+

Name

+

Pmw.Blt - + interface to some BLT widgets and commands

+

+ + + +
+

Description

+

+ This module contains function interfaces to the BLT busy command + as well as the classes Pmw.Blt.Vector, Pmw.Blt.Graph, + Pmw.Blt.Stripchart and Pmw.Blt.Tabset, which are interfaces to + the vector, graph, stripchart and tabset commands of version 2.4 + of the BLT extension to Tk. The interfaces are complete except + for Pmw.Blt.Vector where several creation options, methods and + operations have not been implemented.

+ +

The blt graph and barchart widgets are essentially the same and so + only the graph widget has been ported. The element_create() + method is not implememted for Pmw.Blt.Graph, so instead:

+
  • to create a line element, use the line_create() method and

    + +
  • +
  • to create a bar element, use the bar_create() method.

    + +
+ +

To operate on elements, use the element_*() methods, such as + element_bind(), element_activate(), etc.

+ +

Note: Full documentation of Pmw.Blt.Graph is available in + A User's Guide to Pmw.Blt + written by Bjørn Ove Thue and Hans Petter Langtangen. + You can also download + the full HTML document + of the guide for local viewing.

+ +

+ + +
+

Functions

+The following functions are available.

+
+
Pmw.Blt.busy_forget(window)
+ + Interface to the BLT busy forget command.

+ +

+ + +
+
Pmw.Blt.busy_hold(window, cursor = None)
+ + Interface to the BLT busy hold command.

+ +

+ + +
+
Pmw.Blt.busy_release(window)
+ + Interface to the BLT busy release command.

+ +

+ + +
+
Pmw.Blt.haveblt(window)
+ + Return true if any commands in the BLT extension are available.

+ +

+ + +
+
Pmw.Blt.havebltbusy(window)
+ + Return true if the BLT busy command is available.

+ +

+ + +
+
Pmw.Blt.vector_expr(expression)
+ + Interface to the BLT vector expr command.

+ +

+ + +
+
Pmw.Blt.vector_names(pattern = None)
+ + Interface to the BLT vector names command.

+ +

+ + +
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 25 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ButtonBox.gif b/Pmw/Pmw_1_2/doc/ButtonBox.gif new file mode 100644 index 00000000..402b6b0e Binary files /dev/null and b/Pmw/Pmw_1_2/doc/ButtonBox.gif differ diff --git a/Pmw/Pmw_1_2/doc/ButtonBox.html b/Pmw/Pmw_1_2/doc/ButtonBox.html new file mode 100644 index 00000000..2075f42f --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ButtonBox.html @@ -0,0 +1,306 @@ + + + + + + Pmw.ButtonBox reference manual + + + + +

Pmw.ButtonBox

+ +
+
+

Name

+

Pmw.ButtonBox() - + manager megawidget for buttons +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A button box is a container megawidget which manages a number of + buttons. One of these buttons may be specified as the default and + it will be displayed with the platform specific appearance for a + default button. The buttons may be laid out either horizontally + or vertically.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
orient +
+Initialisation option. Specifies the orientation of the button box. This may be + 'horizontal' or 'vertical'. The default is 'horizontal'.

+ + +
+ +
padx +
+Initialisation option. Specifies a padding distance to leave between each button in the x + direction and also between the buttons and the outer edge of the + button box. The default is 3.

+ + +
+ +
pady +
+Initialisation option. Specifies a padding distance to leave between each button in the y + direction and also between the buttons and the outer edge of the + button box. The default is 3.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
frame +
+If the label component has been created (that is, the labelpos + option is not None), the frame component is created to act as + the container of the buttons created by the add() and + insert() methods. If there is no label component, then no + frame component is created and the hull component acts as the + container. By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+
+

Dynamic components

+

+ Button components are created dynamically by the add() and + insert() methods. By default, the buttons are of type + Tkinter.Button and are created with a component group of + Button.

+

+ + + +
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
add(componentName, **kw)
+Add a button to the end of the button box as a component named + componentName. Any keyword arguments present will be passed to the + constructor when creating the button. If the text keyword + argument is not given, the text option of the button defaults to + componentName. The method returns the component widget.

+ + +
+ +
alignbuttons(when = 'later')
+Set the widths of all the buttons to be the same as the width of + the widest button. If when is 'later', this will occur when the + interpreter next becomes idle, otherwise the resizing will occur + immediately.

+ + +
+ +
button(buttonIndex)
+Return the button specified by buttonIndex, which may have any + of the forms accepted by the index() method.

+ + +
+ +
delete(index)
+Delete the button given by index from the button box. index + may have any of the forms accepted by the index() method.

+ + +
+ +
index(index, forInsert = 0)
+Return the numerical index of the button corresponding to index. + This may be specified in any of the following forms:

+
name
Specifies the button named name.

+ +
+
number
Specifies the button numerically, where 0 corresponds to + the left (or top) button.

+ +
+
Pmw.END
Specifies the right (or bottom) button.

+ +
+
Pmw.DEFAULT
Specifies the current default button.

+ +
+

If forInsert is true, Pmw.END returns the number of buttons rather + than the index of the last button.

+ + + +
+ +
insert(componentName, beforeComponent = 0, **kw)
+Add a button to the button box as a component named + componentName. The button is added just before the button + specified by beforeComponent, which may have any of the forms + accepted by the index() method. Any keyword arguments present + will be passed to the constructor when creating the button. If + the text keyword argument is not given, the text option of the + button defaults to componentName. To add a button to the end of + the button box, use add(). The method returns the component + widget.

+ + +
+ +
invoke(index = Pmw.DEFAULT, noFlash = 0)
+Invoke the callback command associated with the button specified + by index and return the value returned by the callback. + Unless noFlash is true, flash the button to + indicate to the user that something happened. + index may have any of the forms accepted by the index() method.

+ + +
+ +
numbuttons()
+Return the number of buttons in the button box.

+ + +
+ +
setdefault(index)
+Set the default button to the button given by index. This + causes the specified button to be displayed with the platform + specific appearance for a default button. If index is None, + there will be no default button. index may have any of the + forms accepted by the index() method.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create and pack the ButtonBox.
+        self.buttonBox = Pmw.ButtonBox(parent,
+                labelpos = 'nw',
+                label_text = 'ButtonBox:',
+                frame_borderwidth = 2,
+                frame_relief = 'groove')
+        self.buttonBox.pack(fill = 'both', expand = 1, padx = 10, pady = 10)
+
+        # Add some buttons to the ButtonBox.
+        self.buttonBox.add('OK', command = self.ok)
+        self.buttonBox.add('Apply', command = self.apply)
+        self.buttonBox.add('Cancel', command = self.cancel)
+
+        # Set the default button (the one executed when <Return> is hit).
+        self.buttonBox.setdefault('OK')
+        parent.bind('<Return>', self._processReturnKey)
+        parent.focus_set()
+
+        # Make all the buttons the same width.
+        self.buttonBox.alignbuttons()
+
+    def _processReturnKey(self, event):
+        self.buttonBox.invoke()
+
+    def ok(self):
+        print 'You clicked on OK'
+
+    def apply(self):
+        print 'You clicked on Apply'
+
+    def cancel(self):
+        print 'You clicked on Cancel'
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 24 May 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/Color.html b/Pmw/Pmw_1_2/doc/Color.html new file mode 100644 index 00000000..e004f85e --- /dev/null +++ b/Pmw/Pmw_1_2/doc/Color.html @@ -0,0 +1,326 @@ + + + + + + Pmw.Color reference manual + + + + +

Pmw.Color

+ +
+

Name

+

Pmw.Color - + contains functions for handling colors and color schemes

+

+ + + +
+

Description

+

+ This module is a set of functions for manipulating colors and for + modifying the color scheme of an application or a widget. Many of + the functions in this module take or return colors. These values + may represent colors in the following ways:

+
name
a standard color name, eg 'orange' or '#ffa500'

+ +
+
rgb
a 3-element sequence of red, green and blue intensities + each between 0.0 (dark) and 1.0 (light), eg [1.0, 0.6, 0.0].

+ +
+
hsi
a 3-element sequence (hue, saturation, + intensity). The value of hue is between 0.0 and 2pi + (6.28318) giving a range of colors covering, in order, red, + orange, yellow green, cyan, blue, magenta and back to red. + The value of saturation is between 0.0 (grey) and 1.0 + (brilliant) and the value of intensity is between 0.0 (dark) + and 1.0 (bright).

+ +
+ +

As used in these functions, the brightness of a color is the + perceived grey level of the color as registered by the human eye. + For example, even though the colors red, blue and yellow have the + same intensity (1.0), they have different brightnesses, 0.299, + 0.114 and 0.886 respectively, reflecting the different way these + colors appear to the eye. The brightness of a color is a value + between 0.0 (dark) and 1.0 (bright).

+ +

A color scheme is a set of colors defined for each of the + default color options in the Tk option database. Color schemes + can be used in two ways. Firstly, using Pmw.Color.setscheme(), + the Tk option database can be set to the values in the color + scheme. This will not have any effect on currently existing + widgets, but any new widgets created after setting the options + will have these colors as their defaults. Secondly, using + Pmw.Color.changecolor() the color scheme can be used to change + the colors of a widget and all its child widgets.

+ +

A color scheme is specified by defining one or more color options + (one of the defined options must be background). Not all + options need be specified - if any options are not defined, they + are calculated from the other colors. These are the options used + by a color scheme, together with their values if not specified:

+
 background:            (must be specified)
+ foreground:            black
+ activeForeground:      same as foreground
+ insertBackground:      same as foreground
+ selectForeground:      same as foreground
+ highlightColor:        same as foreground
+ disabledForeground:    between fg and bg but closer to bg
+ highlightBackground:   same as background
+ activeBackground:      a little lighter that bg
+ selectBackground:      a little darker that bg
+ troughColor:           a little darker that bg
+ selectColor:           yellow
+ + +

There are many functions in this module. As well as + Pmw.Color.setscheme() and Pmw.Color.changecolor(), some of the + most useful are Pmw.Color.spectrum(), + Pmw.Color.changebrightness() and + Pmw.Color.getdefaultpalette().

+ +

+ + +
+

Functions

+The following functions are available.

+
+
Pmw.Color.average(rgb1, rgb2, fraction)
+ + Return an rgb color fraction of the way "between" the colors + rgb1 and rgb2, where fraction must be between 0.0 and + 1.0. If fraction is close to 0.0, then the color returned + will be close to rgb1. If it is close to 1.0, then the color + returned will be close to rgb2. If it is near 0.5, then the + color returned will be half way between the two colors.

+ +

+ + +
+
Pmw.Color.bhi2saturation(brightness, hue, intensity)
+ + Return the saturation of the color represented by brightness, + hue and intensity.

+ +

+ + +
+
Pmw.Color.bordercolors(root, colorName)
+ + Return a tuple (light, dark) of color names that can be used as + the light and dark border shadows on a widget where the background + is colorName. This is the same method that Tk uses for shadows + when drawing reliefs on widget borders. The root argument is + only used to query Tk for the rgb values of colorName.

+ +

+ + +
+
Pmw.Color.changebrightness(root, colorName, brightness)
+ + Find the hue of the color colorName and return a color of this + hue with the required brightness. If brightness is None, + return the name of color with the given hue and with saturation + and intensity both 1.0. The root argument is only used to + query Tk for the rgb values of colorName.

+ +

+ + +
+
Pmw.Color.changecolor(widget, background = None, **kw)
+ + Change the color of widget and all its child widgets according + to the color scheme specified by the other arguments. This is done + by modifying all of the color options of existing widgets that + have the default value. The color options are the lower case + versions of those described in the color scheme section. Any + options which are different to the previous color scheme (or the + defaults, if this is the first call) are not changed.

+ +

For example to change a widget to have a red color scheme with a + white foreground:

+ +
 Pmw.Color.changecolor(widget,
+     background = 'red3', foreground = 'white')
+ +

The colors of widgets created after this call will not be + affected.

+ +

Note that widget must be a Tk widget or toplevel. To change the + color of a Pmw megawidget, use it's hull component. For example:

+ +
 widget = megawidget.component('hull')
+ Pmw.Color.changecolor(widget, background = 'red3')
+ +

+ + +
+
Pmw.Color.correct(rgb, correction)
+ + Return the "corrected" value of rgb. This can be used to + correct for dull monitors. If correction is less than 1.0, + the color is dulled. If correction is greater than 1.0, the + color is brightened.

+ +

+ + +
+
Pmw.Color.getdefaultpalette(root)
+ + Return a dictionary of the default values of the color options + described in the color scheme section.

+ +

To do this, a few widgets are created as children of root, their + defaults are queried, and then the widgets are destroyed. (Tk + supplies no other way to get widget default values.)

+ +

Note that root must be a Tk widget or toplevel. To use a Pmw + megawidget as the root, use it's hull component. For example:

+ +
 root = megawidget.component('hull')
+ Pmw.Color.getdefaultpalette(root)
+ +

+ + +
+
Pmw.Color.hsi2rgb(hue, saturation, intensity)
+ + Return the rgb representation of the color represented by hue, + saturation and intensity.

+ +

+ + +
+
Pmw.Color.hue2name(hue, brightness = None)
+ + Return the name of the color with the specified hue and + brightness. If hue is None, return a grey of the requested + brightness. Otherwise, the value of hue should be as described + above. If brightness is None, return the name of color with + the given hue and with saturation and intensity both 1.0.

+ +

+ + +
+
Pmw.Color.name2rgb(root, colorName, asInt = 0)
+ + Return colorName as an rgb value. If asInt is true, then + the elements of the return sequence are in the range 0 to + 65535 rather than 0.0 to 1.0. The root argument is only + used to query Tk for the rgb values of colorName.

+ +

+ + +
+
Pmw.Color.rgb2brightness(rgb)
+ + Return the brightness of the color represented by rgb.

+ +

+ + +
+
Pmw.Color.rgb2hsi(rgb)
+ + Return a tuple (hue, saturation, intensity) corresponding to + the color specified by the rgb sequence.

+ +

+ + +
+
Pmw.Color.rgb2name(rgb)
+ + Return the name of the color represented by rgb as a string of + the form '#RRGGBB' suitable for use with Tk color functions.

+ +

+ + +
+
Pmw.Color.setscheme(root, background = None, **kw)
+ + Set the color scheme for the application by setting default colors + (in the Tk option database of the root window of root) according + to the color scheme specified by the other arguments. This will + affect the initial colours of all widgets created after the call + to this function.

+ +

For example to initialise an application to have a red color + scheme with a white foreground:

+ +
 Pmw.Color.setscheme(root,
+     background = 'red3', foreground = 'white')
+ +

This function does not modify the colors of already existing + widgets. Use Pmw.Color.changecolor() to do this.

+ +

Note that root must be a Tk widget or toplevel. To use the Tk + option database of the root window of a Pmw megawidget, use the + megawidget's hull component. For example:

+ +
 root = megawidget.component('hull')
+ Pmw.Color.setscheme(root, background = 'red3')
+ +

+ + +
+
Pmw.Color.spectrum(numColors, correction = 1.0, saturation = 1.0, intensity = 1.0, extraOrange = 1, returnHues = 0)
+ + Return a list of numColors different colors making up a + spectrum. If extraOrange is false, the colors are evenly + spaced by hue from one end of the spectrum (red) to the other + (magenta). If extraOrange is true, the hues are not quite + evenly spaced - the hues around orange are emphasised, thus + preventing the spectrum from appearing to have to many cool + hues.

+ +

If returnHues is false, the return values are the names of the + colors represented by the hues together with saturation and + intensity and corrected by correction.

+ +

If returnHues is true, the return values are hues.

+ +

+ + +
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 25 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ComboBox.gif b/Pmw/Pmw_1_2/doc/ComboBox.gif new file mode 100644 index 00000000..31fee77c Binary files /dev/null and b/Pmw/Pmw_1_2/doc/ComboBox.gif differ diff --git a/Pmw/Pmw_1_2/doc/ComboBox.html b/Pmw/Pmw_1_2/doc/ComboBox.html new file mode 100644 index 00000000..0be8d68c --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ComboBox.html @@ -0,0 +1,363 @@ + + + + + + Pmw.ComboBox reference manual + + + + +

Pmw.ComboBox

+ +
+
+

Name

+

Pmw.ComboBox() - + dropdown or simple combination box +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A combobox contains an entry field and an associated scrolled + listbox. When an item in the listbox is selected, it is displayed + in the entry field. Optionally, the user may also edit the entry + field directly.

+ +

For a simple combobox, the scrolled listbox is displayed beneath + the entry field. For a dropdown combobox (the default), the + scrolled listbox is displayed in a window which pops up beneath + the entry field when the user clicks on an arrow button on the + right of the entry field. Either style allows an optional label.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
autoclear +
+Initialisation option. If both autoclear and history are true, clear the entry field + whenever <Return> is pressed, after adding the value to the + history list. The default is 0.

+ + +
+ +
buttonaspect +
+Initialisation option. The width of the arrow button as a proportion of the height. The + height of the arrow button is set to the height of the entry + widget. The default is 1.0.

+ + +
+ +
dropdown +
+Initialisation option. Specifies whether the combobox should be dropdown or simple. The default is 1.

+ + +
+ +
fliparrow +
+Initialisation option. If true, the arrow button is draw upside down when the listbox is + being displayed. Used only in dropdown megawidgets. The default is 0.

+ + +
+ +
history +
+Initialisation option. When <Return> is pressed in the entry field, the current value + of the entry field is appended to the listbox if history is + true. The default is 1.

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
listheight +
+Initialisation option. The height, in pixels, of the dropdown listbox. The default is 200.

+ + +
+ +
selectioncommand +
+The function to call when an item is selected. + If this function takes a long time to run, and you want the entry + field to be updated quickly, call update_idletasks() at the + beginning of the function. Alternatively, wrap the function using + Pmw.busycallback(). The default is None.

+ + +
+ +
sticky +
+Initialisation option. The default is 'ew'.

+ + +
+ +
unique +
+Initialisation option. If both unique and history are true, the current value of the + entry field is not added to the listbox if it is already in the + list. The default is 1.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
arrowbutton +
+In a dropdown combobox, the button to popup the listbox. By default, this component is a Tkinter.Canvas.

+ + +
+ +
entryfield +
+The entry field where the current selection is displayed. By default, this component is a Pmw.EntryField.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
popup +
+In a dropdown combobox, the dropdown window. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
scrolledlist +
+The scrolled listbox which displays the items to select. By default, this component is a Pmw.ScrolledListBox.

+ + +
+
+

Component aliases

+Sub-components of components of this megawidget +may be accessed via the following aliases.

+
entry +
+Alias for entryfield_entry. +
+
listbox +
+Alias for scrolledlist_listbox. +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +In addition, methods from the following classes +are forwarded by this megawidget. +Methods from Pmw.ScrolledListBox +are forwarded to the +scrolledlist component. +Methods from Pmw.EntryField +are forwarded to the +entryfield component. +Forwarded methods are searched in the order given. +

+ +
bbox(index)
+This method is explicitly forwarded to the scrolledlist + component's bbox() method. Without this explicit forwarding, + the bbox() method (aliased to grid_bbox()) of the hull would + be invoked, which is probably not what the programmer intended.

+ + +
+ +
clear()
+Delete all items from the scrolled listbox and delete all text + from the entry widget.

+ + +
+ +
get(first = None, last = None)
+This is the same as the get() method of the scrolledlist + component, except that if first is None then + the value of the entry field is returned.

+ + +
+ +
invoke()
+If a dropdown combobox, display the dropdown listbox. In a simple + combobox, select the currently selected item in the listbox, + call the selectioncommand and return the result.

+ + +
+ +
selectitem(index, setentry = 1)
+Select the item in the listbox specified by index which may be + either one of the items in the listbox or the integer index of one + of the items in the listbox.

+

If setentry is true, also set the entry field to the selected + item.

+ + + +
+ +
size()
+This method is explicitly forwarded to the scrolledlist + component's size() method. Without this explicit forwarding, + the size() method (aliased to grid_size()) of the hull would + be invoked, which is probably not what the programmer intended.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        parent.configure(background = 'white')
+
+        # Create and pack the widget to be configured.
+        self.target = Tkinter.Label(parent,
+                relief = 'sunken',
+                padx = 20,
+                pady = 20,
+        )
+        self.target.pack(fill = 'x', padx = 8, pady = 8)
+
+        # Create and pack the simple ComboBox.
+        words = ('Monti', 'Python', 'ik', 'den', 'Holie', 'Grailen', '(Bok)')
+        simple = Pmw.ComboBox(parent,
+                label_text = 'Simple ComboBox:',
+                labelpos = 'nw',
+                selectioncommand = self.changeText,
+                scrolledlist_items = words,
+                dropdown = 0,
+        )
+        simple.pack(side = 'left', fill = 'both',
+                expand = 1, padx = 8, pady = 8)
+
+        # Display the first text.
+        first = words[0]
+        simple.selectitem(first)
+        self.changeText(first)
+
+        # Create and pack the dropdown ComboBox.
+        colours = ('cornsilk1', 'snow1', 'seashell1', 'antiquewhite1',
+                'bisque1', 'peachpuff1', 'navajowhite1', 'lemonchiffon1',
+                'ivory1', 'honeydew1', 'lavenderblush1', 'mistyrose1')
+        dropdown = Pmw.ComboBox(parent,
+                label_text = 'Dropdown ComboBox:',
+                labelpos = 'nw',
+                selectioncommand = self.changeColour,
+                scrolledlist_items = colours,
+        )
+        dropdown.pack(side = 'left', anchor = 'n',
+                fill = 'x', expand = 1, padx = 8, pady = 8)
+
+        # Display the first colour.
+        first = colours[0]
+        dropdown.selectitem(first)
+        self.changeColour(first)
+
+    def changeColour(self, colour):
+        print 'Colour: ' + colour
+        self.target.configure(background = colour)
+
+    def changeText(self, text):
+        print 'Text: ' + text
+        self.target.configure(text = text)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 1 November 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ComboBoxDialog.gif b/Pmw/Pmw_1_2/doc/ComboBoxDialog.gif new file mode 100644 index 00000000..011fde57 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/ComboBoxDialog.gif differ diff --git a/Pmw/Pmw_1_2/doc/ComboBoxDialog.html b/Pmw/Pmw_1_2/doc/ComboBoxDialog.html new file mode 100644 index 00000000..e139f11c --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ComboBoxDialog.html @@ -0,0 +1,286 @@ + + + + + + Pmw.ComboBoxDialog reference manual + + + + +

Pmw.ComboBoxDialog

+ +
+
+

Name

+

Pmw.ComboBoxDialog() - + selection dialog displaying a list and an entry field +

+ + +
+

Inherits

+Pmw.Dialog
+
+

Description

+

+ A combobox dialog is a dialog window which displays a list and + an entry field which can be used to prompt the user for a value.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
borderx +
+Initialisation option. The padding to the left and right of the combobox. The default is 10.

+ + +
+ +
bordery +
+Initialisation option. The padding above and below the combobox. The default is 10.

+ + +
+ +
buttonboxpos +
+Initialisation option. Specifies on which side of the dialog window to place the button + box. Must be one of 'n', 's', 'e' or 'w'. The default is 's'.

+ + +
+ +
buttons +
+This must be a tuple or a list and specifies the names on the + buttons in the button box. The default is ('OK',).

+ + +
+ +
command +
+Specifies a function to call whenever a button in the button box + is invoked or the window is deleted by the window manager. The + function is called with a single argument, which is the name of + the button which was invoked, or None if the window was deleted + by the window manager.

+

If the value of command is not callable, the default behaviour + is to deactivate the window if it is active, or withdraw the + window if it is not active. If it is deactivated, deactivate() + is called with the button name or None as described above. The default is None.

+ + + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
defaultbutton +
+Specifies the default button in the button box. If the <Return> + key is hit when the dialog has focus, the default button will be + invoked. If defaultbutton is None, there will be no default + button and hitting the <Return> key will have no effect. The default is None.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
separatorwidth +
+Initialisation option. If this is greater than 0, a separator line with the specified + width will be created between the button box and the child site, + as a component named separator. Since the default border of the + button box and child site is raised, this option does not + usually need to be set for there to be a visual separation between + the button box and child site. The default is 0.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
buttonbox +
+This is the button box containing the buttons for the dialog. By + default it is created with the options + (hull_borderwidth = 1, hull_relief = 'raised'). By default, this component is a Pmw.ButtonBox.

+ + +
+ +
combobox +
+The combobox for the user to enter a value. By default it is + created using the option dropdown = 0. By default, this component is a Pmw.ComboBox.

+ + +
+ +
dialogchildsite +
+This is the child site for the dialog, which may be used to + specialise the megawidget by creating other widgets within it. By + default it is created with the options + (borderwidth = 1, relief = 'raised'). By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
separator +
+If the separatorwidth initialisation option is non-zero, the + separator component is the line dividing the area between the + button box and the child site. By default, this component is a Tkinter.Frame.

+ + +
+
+

Component aliases

+Sub-components of components of this megawidget +may be accessed via the following aliases.

+
entry +
+Alias for combobox_entry. +
+
label +
+Alias for combobox_label. +
+
listbox +
+Alias for combobox_listbox. +
+
scrolledlist +
+Alias for combobox_scrolledlist. +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.Dialog. +In addition, methods from the +Pmw.ComboBox class +are forwarded by this megawidget to the +combobox component. +

+ +
bbox(index)
+This method is explicitly forwarded to the combobox component's + bbox() method. Without this explicit forwarding, the bbox() + method (aliased to grid_bbox()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+ +
size()
+This method is explicitly forwarded to the combobox component's + size() method. Without this explicit forwarding, the size() + method (aliased to grid_size()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the dialog.
+        self.dialog = Pmw.ComboBoxDialog(parent,
+            title = 'My ComboBoxDialog',
+            buttons = ('OK', 'Cancel'),
+            defaultbutton = 'OK',
+            combobox_labelpos = 'n',
+            label_text = 'What do you think of Pmw?',
+            scrolledlist_items = ('Cool man', 'Cool', 'Good', 'Bad', 'Gross'))
+        self.dialog.withdraw()
+
+        # Create button to launch the dialog.
+        w = Tkinter.Button(parent,
+                text = 'Show combo box dialog',
+                command = self.doit)
+        w.pack(padx = 8, pady = 8)
+
+    def doit(self):
+        result = self.dialog.activate()
+        print 'You clicked on', result, self.dialog.get()
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/Counter.gif b/Pmw/Pmw_1_2/doc/Counter.gif new file mode 100644 index 00000000..20c33222 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/Counter.gif differ diff --git a/Pmw/Pmw_1_2/doc/Counter.html b/Pmw/Pmw_1_2/doc/Counter.html new file mode 100644 index 00000000..a52595e8 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/Counter.html @@ -0,0 +1,455 @@ + + + + + + Pmw.Counter reference manual + + + + +

Pmw.Counter

+ +
+
+

Name

+

Pmw.Counter() - + entry field with up and down arrow buttons +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A counter contains an entry field and two arrow buttons to + increment and decrement the value in the entry field. Standard + counting types include numbers, times and dates. A user defined + counting function may also be supplied for specialised counting. + Counting can be used in combination with the entry field's + validation. The components may be laid out horizontally or + vertically.

+ +

Each time an arrow button is pressed the value displayed in the + entry field is incremented or decremented by the value of the + increment option. If the new value is invalid (according to the + entry field's validate option, perhaps due to exceeding minimum + or maximum limits), the old value is restored.

+ +

When an arrow button is pressed and the value displayed is not an + exact multiple of the increment, it is "truncated" up or down to + the nearest increment.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
autorepeat +
+If true, the counter will continue to count up or down while an + arrow button is held pressed down. The default is 1.

+ + +
+ +
buttonaspect +
+Initialisation option. Specifies the width of the arrow buttons as a proportion of their + height. Values less than 1.0 will produce thin arrow buttons. + Values greater than 1.0 will produce fat arrow buttons. The default is 1.0.

+ + +
+ +
datatype +
+Specifies how the counter should count up and down.

+

The most general way to specify the datatype option is as a + dictionary. The kind of counting is specified by the 'counter' + dictionary field, which may be either a function or the name of + one of the standard counters described below. If the dictionary + does not have a 'counter' field, the field defaults to + 'numeric'.

+ +

Any other fields in the dictionary are passed on to the counter + function as keyword arguments.

+ +

If datatype is not a dictionary, then it is equivalent to + specifying it as a dictionary with a single 'counter' field. + For example, datatype = 'real' is equivalent to + datatype = {'counter' : 'real'}.

+ +

The standard counters are:

+ +
'numeric'
An integer number, as accepted by string.atol().

+ +
+
'integer'
Same as 'numeric'.

+ +
+
'real'
A real number, as accepted by string.atof(). This + counter accepts a 'separator' argument, which specifies + the character used to represent the decimal point. The + default 'separator' is '.'.

+ +
+
'time'
A time specification, as accepted by + Pmw.timestringtoseconds(). This counter accepts a + 'separator' argument, which specifies the character used to + separate the time fields. The default separator is ':'. + This counter also accepts a 'time24' argument. If this is + true, the time value is converted to a value between + '00:00:00' and '23:59:59'. The default is false.

+ +
+
'date'
A date specification, as accepted by + Pmw.datestringtojdn(). This counter accepts a 'separator' + argument, which specifies the character used to separate the + three date fields. The default is '/'. This counter also + accepts a 'format' argument, which is passed to + Pmw.datestringtojdn() to specify the desired ordering of the + fields. The default is 'ymd'. + This counter also accepts a 'yyyy' argument. If this is + false, the year field will be displayed as the year within the + century, otherwise it will be fully displayed. In both cases + it will be displayed with at least 2 digits, using leading + zeroes. The default is false.

+ +
+

If the 'counter' dictionary field is a function, then it will be + called whenever the counter is to be incremented or decremented. + The function is called with at least three arguments, the first + three being (text, factor, increment), where text is the + current contents of the entry field, factor is 1 when + incrementing or -1 when decrementing, and increment is the + value of the increment megawidget option.

+ +

The other arguments are keyword arguments made up of the fields of + the datatype dictionary (excluding the 'counter' field).

+ +

The counter function should return a string representing the + incremented or decremented value. It should raise a + ValueError exception if the text is invalid. In this case the + bell is rung and the entry text is not changed.

+ +

The default for datatype is numeric.

+ + + +
+ +
increment +
+Specifies how many units should be added or subtracted when the + counter is incremented or decremented. If the currently displayed + value is not a multiple of increment, the value is changed to + the next multiple greater or less than the current value.

+

For the number datatypes, the value of increment is a number. + For the 'time' datatype, the value is in seconds. For the + 'date' datatype, the value is in days. The default is 1.

+ + + +
+ +
initwait +
+Specifies the initial delay (in milliseconds) before a depressed + arrow button automatically starts to repeat counting. The default is 300.

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
orient +
+Initialisation option. Specifies whether the arrow buttons should appear to the left and + right of the entry field ('horizontal') or above and below + ('vertical'). The default is 'horizontal'.

+ + +
+ +
padx +
+Initialisation option. Specifies a padding distance to leave around the arrow buttons in + the x direction. The default is 0.

+ + +
+ +
pady +
+Initialisation option. Specifies a padding distance to leave around the arrow buttons in + the y direction. The default is 0.

+ + +
+ +
repeatrate +
+Specifies the delay (in milliseconds) between automatic counts + while an arrow button is held pressed down. The default is 50.

+ + +
+ +
sticky +
+Initialisation option. The default is 'ew'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
downarrow +
+The arrow button used for decrementing the counter. Depending on + the value of orient, it will appear on the left or below the + entry field. By default, this component is a Tkinter.Canvas. Its component group is Arrow.

+ + +
+ +
entryfield +
+The entry field widget where the text is entered, displayed and + validated. By default, this component is a Pmw.EntryField.

+ + +
+ +
frame +
+If the label component has been created (that is, the labelpos + option is not None), the frame component is created to act as + the container of the entry field and arrow buttons. If there is + no label component, then no frame component is created and the + hull component acts as the container. In either case the border + around the container of the entry field and arrow buttons will be + raised (but not around the label). By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
uparrow +
+The arrow button used for incrementing the counter. Depending on + the value of orient, it will appear on the right or above the + entry field. By default, this component is a Tkinter.Canvas. Its component group is Arrow.

+ + +
+
+

Component aliases

+Sub-components of components of this megawidget +may be accessed via the following aliases.

+
entry +
+Alias for entryfield_entry. +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +In addition, methods from the +Pmw.EntryField class +are forwarded by this megawidget to the +entryfield component. +

+ +
decrement()
+Decrement the counter once, as if the down arrow had been pressed.

+ + +
+ +
increment()
+Increment the counter once, as if the up arrow had been pressed.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Need to use long ints here because on the Macintosh the maximum size
+        # of an integer is smaller than the value returned by time.time().
+        now = (long(time.time()) / 300) * 300
+
+        # Create the Counters.
+        self._date = Pmw.Counter(parent,
+                labelpos = 'w',
+                label_text = 'Date (4-digit year):',
+                entryfield_value =
+                        time.strftime('%d/%m/%Y', time.localtime(now)),
+                entryfield_command = self.execute,
+                entryfield_validate = {'validator' : 'date', 'format' : 'dmy'},
+                datatype = {'counter' : 'date', 'format' : 'dmy', 'yyyy' : 1})
+
+        self._isodate = Pmw.Counter(parent,
+                labelpos = 'w',
+                label_text = 'ISO-Date (4-digit year):',
+                entryfield_value =
+                        time.strftime('%Y-%m-%d', time.localtime(now)),
+                entryfield_command = self.execute,
+                entryfield_validate = {'validator' : 'date', 'format' : 'ymd',
+                        'separator' : '-' },
+                datatype = {'counter' : 'date', 'format' : 'ymd', 'yyyy' : 1,
+                        'separator' : '-' })
+
+        self._time = Pmw.Counter(parent,
+                labelpos = 'w',
+                label_text = 'Time:',
+                entryfield_value =
+                        time.strftime('%H:%M:%S', time.localtime(now)),
+                entryfield_validate = {'validator' : 'time',
+                        'min' : '00:00:00', 'max' : '23:59:59',
+                        'minstrict' : 0, 'maxstrict' : 0},
+                datatype = {'counter' : 'time', 'time24' : 1},
+                increment=5*60)
+        self._real = Pmw.Counter(parent,
+                labelpos = 'w',
+                label_text = 'Real (with comma)\nand extra\nlabel lines:',
+                label_justify = 'left',
+                entryfield_value = '1,5',
+                datatype = {'counter' : 'real', 'separator' : ','},
+                entryfield_validate = {'validator' : 'real',
+                        'min' : '-2,0', 'max' : '5,0',
+                        'separator' : ','},
+                increment = 0.1)
+        self._custom = Pmw.Counter(parent,
+                labelpos = 'w',
+                label_text = 'Custom:',
+                entryfield_value = specialword[:4],
+                datatype = _custom_counter,
+                entryfield_validate = _custom_validate)
+        self._int = Pmw.Counter(parent,
+                labelpos = 'w',
+                label_text = 'Vertical integer:',
+                orient = 'vertical',
+                entry_width = 2,
+                entryfield_value = 50,
+                entryfield_validate = {'validator' : 'integer',
+                        'min' : 0, 'max' : 99}
+        )
+
+        counters = (self._date, self._isodate, self._time, self._real,
+                self._custom)
+        Pmw.alignlabels(counters)
+
+        # Pack them all.
+        for counter in counters:
+            counter.pack(fill='both', expand=1, padx=10, pady=5)
+        self._int.pack(padx=10, pady=5)
+
+    def execute(self):
+        print 'Return pressed, value is', self._date.get()
+
+specialword = 'Monti Python ik den Holie Grailen (Bok)'
+
+def _custom_validate(text):
+    if string.find(specialword, text) == 0:
+        return 1
+    else:
+        return -1
+
+def _custom_counter(text, factor, increment):
+    # increment is ignored here.
+    if string.find(specialword, text) == 0:
+        length = len(text)
+        if factor == 1:
+            if length >= len(specialword):
+                raise ValueError, 'maximum length reached'
+            return specialword[:length + 1]
+        else:
+            if length == 0:
+                raise ValueError, 'empty string'
+            return specialword[:length - 1]
+    else:
+        raise ValueError, 'bad string ' + text
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 24 May 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/CounterDialog.gif b/Pmw/Pmw_1_2/doc/CounterDialog.gif new file mode 100644 index 00000000..dd833420 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/CounterDialog.gif differ diff --git a/Pmw/Pmw_1_2/doc/CounterDialog.html b/Pmw/Pmw_1_2/doc/CounterDialog.html new file mode 100644 index 00000000..ec8ed83f --- /dev/null +++ b/Pmw/Pmw_1_2/doc/CounterDialog.html @@ -0,0 +1,299 @@ + + + + + + Pmw.CounterDialog reference manual + + + + +

Pmw.CounterDialog

+ +
+
+

Name

+

Pmw.CounterDialog() - + selection dialog displaying a counter +

+ + +
+

Inherits

+Pmw.Dialog
+
+

Description

+

+ A counter dialog is a dialog window which displays a counter + which can be used to prompt the user for a value.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
borderx +
+Initialisation option. The padding to the left and right of the counter. The default is 20.

+ + +
+ +
bordery +
+Initialisation option. The padding above and below the counter. The default is 20.

+ + +
+ +
buttonboxpos +
+Initialisation option. Specifies on which side of the dialog window to place the button + box. Must be one of 'n', 's', 'e' or 'w'. The default is 's'.

+ + +
+ +
buttons +
+This must be a tuple or a list and specifies the names on the + buttons in the button box. The default is ('OK',).

+ + +
+ +
command +
+Specifies a function to call whenever a button in the button box + is invoked or the window is deleted by the window manager. The + function is called with a single argument, which is the name of + the button which was invoked, or None if the window was deleted + by the window manager.

+

If the value of command is not callable, the default behaviour + is to deactivate the window if it is active, or withdraw the + window if it is not active. If it is deactivated, deactivate() + is called with the button name or None as described above. The default is None.

+ + + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
defaultbutton +
+Specifies the default button in the button box. If the <Return> + key is hit when the dialog has focus, the default button will be + invoked. If defaultbutton is None, there will be no default + button and hitting the <Return> key will have no effect. The default is None.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
separatorwidth +
+Initialisation option. If this is greater than 0, a separator line with the specified + width will be created between the button box and the child site, + as a component named separator. Since the default border of the + button box and child site is raised, this option does not + usually need to be set for there to be a visual separation between + the button box and child site. The default is 0.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
buttonbox +
+This is the button box containing the buttons for the dialog. By + default it is created with the options + (hull_borderwidth = 1, hull_relief = 'raised'). By default, this component is a Pmw.ButtonBox.

+ + +
+ +
counter +
+The counter for the user to enter a value. By default, this component is a Pmw.Counter.

+ + +
+ +
dialogchildsite +
+This is the child site for the dialog, which may be used to + specialise the megawidget by creating other widgets within it. By + default it is created with the options + (borderwidth = 1, relief = 'raised'). By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
separator +
+If the separatorwidth initialisation option is non-zero, the + separator component is the line dividing the area between the + button box and the child site. By default, this component is a Tkinter.Frame.

+ + +
+
+

Component aliases

+Sub-components of components of this megawidget +may be accessed via the following aliases.

+
entry +
+Alias for counter_entryfield_entry. +
+
entryfield +
+Alias for counter_entryfield. +
+
label +
+Alias for counter_label. +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.Dialog. +In addition, methods from the +Pmw.Counter class +are forwarded by this megawidget to the +counter component. +

+ +
deleteentry(first, last = None)
+Delete text from the counter's entry widget. An alias for + component('entry').delete().

+ + +
+ +
indexentry(index)
+An alias for component('entry').index().

+ + +
+ +
insertentry(index, text)
+Insert text into the counter's entry widget. An alias for + component('entry').insert().

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the dialog to prompt for the number of times to ring the bell.
+        self.dialog = Pmw.CounterDialog(parent,
+            label_text = 'Enter the number of times to\n' + \
+                    'sound the bell (1 to 5)\n',
+            counter_labelpos = 'n',
+            entryfield_value = 2,
+            counter_datatype = 'numeric',
+            entryfield_validate =
+                {'validator' : 'numeric', 'min' : 1, 'max' : 5},
+            buttons = ('OK', 'Cancel'),
+            defaultbutton = 'OK',
+            title = 'Bell ringing',
+            command = self.execute)
+        self.dialog.withdraw()
+
+        # Create button to launch the dialog.
+        w = Tkinter.Button(parent, text = 'Show counter dialog',
+                command = self.dialog.activate)
+        w.pack(padx = 8, pady = 8)
+
+    def execute(self, result):
+        if result is None or result == 'Cancel':
+            print 'Bell ringing cancelled'
+            self.dialog.deactivate()
+        else:
+            count = self.dialog.get()
+            if not self.dialog.valid():
+                print 'Invalid entry: "' + count + '"'
+            else:
+                print 'Ringing the bell ' + count + ' times'
+                for num in range(string.atoi(count)):
+                    if num != 0:
+                        self.dialog.after(200)
+                    self.dialog.bell()
+                self.dialog.deactivate()
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/Dialog.gif b/Pmw/Pmw_1_2/doc/Dialog.gif new file mode 100644 index 00000000..34834576 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/Dialog.gif differ diff --git a/Pmw/Pmw_1_2/doc/Dialog.html b/Pmw/Pmw_1_2/doc/Dialog.html new file mode 100644 index 00000000..1e3c8886 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/Dialog.html @@ -0,0 +1,286 @@ + + + + + + Pmw.Dialog reference manual + + + + +

Pmw.Dialog

+ +
+
+

Name

+

Pmw.Dialog() - + toplevel window with button box +

+ + +
+

Inherits

+Pmw.MegaToplevel
+
+

Description

+

+ A dialog is a toplevel window composed of a button box and a child + site area. The child site area can be used to specialise the + megawidget by creating other widgets within it. This can be done + by using this class directly or by deriving from it.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
buttonboxpos +
+Initialisation option. Specifies on which side of the dialog window to place the button + box. Must be one of 'n', 's', 'e' or 'w'. The default is 's'.

+ + +
+ +
buttons +
+This must be a tuple or a list and specifies the names on the + buttons in the button box. The default is ('OK',).

+ + +
+ +
command +
+Specifies a function to call whenever a button in the button box + is invoked or the window is deleted by the window manager. The + function is called with a single argument, which is the name of + the button which was invoked, or None if the window was deleted + by the window manager.

+

If the value of command is not callable, the default behaviour + is to deactivate the window if it is active, or withdraw the + window if it is not active. If it is deactivated, deactivate() + is called with the button name or None as described above. The default is None.

+ + + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
defaultbutton +
+Specifies the default button in the button box. If the <Return> + key is hit when the dialog has focus, the default button will be + invoked. If defaultbutton is None, there will be no default + button and hitting the <Return> key will have no effect. The default is None.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
separatorwidth +
+Initialisation option. If this is greater than 0, a separator line with the specified + width will be created between the button box and the child site, + as a component named separator. Since the default border of the + button box and child site is raised, this option does not + usually need to be set for there to be a visual separation between + the button box and child site. The default is 0.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
buttonbox +
+This is the button box containing the buttons for the dialog. By + default it is created with the options + (hull_borderwidth = 1, hull_relief = 'raised'). By default, this component is a Pmw.ButtonBox.

+ + +
+ +
dialogchildsite +
+This is the child site for the dialog, which may be used to + specialise the megawidget by creating other widgets within it. By + default it is created with the options + (borderwidth = 1, relief = 'raised'). By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
separator +
+If the separatorwidth initialisation option is non-zero, the + separator component is the line dividing the area between the + button box and the child site. By default, this component is a Tkinter.Frame.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaToplevel. +

+ +
interior()
+Return the child site for the dialog. This is the same as + component('dialogchildsite').

+ + +
+ +
invoke(index = Pmw.DEFAULT)
+Invoke the command specified by the command option as if the + button specified by index had been pressed and return the + result. index may have any of the forms accepted by the + Pmw.ButtonBox index() method.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create two buttons to launch the dialog.
+        w = Tkinter.Button(parent, text = 'Show application modal dialog',
+                command = self.showAppModal)
+        w.pack(padx = 8, pady = 8)
+
+        w = Tkinter.Button(parent, text = 'Show global modal dialog',
+                command = self.showGlobalModal)
+        w.pack(padx = 8, pady = 8)
+
+        w = Tkinter.Button(parent, text = 'Show dialog with "no grab"',
+                command = self.showDialogNoGrab)
+        w.pack(padx = 8, pady = 8)
+
+        w = Tkinter.Button(parent, text =
+                    'Show toplevel window which\n' +
+                    'will not get a busy cursor',
+                command = self.showExcludedWindow)
+        w.pack(padx = 8, pady = 8)
+
+        # Create the dialog.
+        self.dialog = Pmw.Dialog(parent,
+            buttons = ('OK', 'Apply', 'Cancel', 'Help'),
+            defaultbutton = 'OK',
+            title = 'My dialog',
+            command = self.execute)
+        self.dialog.withdraw()
+
+        # Add some contents to the dialog.
+        w = Tkinter.Label(self.dialog.interior(),
+            text = 'Pmw Dialog\n(put your widgets here)',
+            background = 'black',
+            foreground = 'white',
+            pady = 20)
+        w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)
+
+        # Create the window excluded from showbusycursor.
+        self.excluded = Pmw.MessageDialog(parent,
+            title = 'I still work',
+            message_text =
+                'This window will not get\n' +
+                'a busy cursor when modal dialogs\n' +
+                'are activated.  In addition,\n' +
+                'you can still interact with\n' +
+                'this window when a "no grab"\n' +
+                'modal dialog is displayed.')
+        self.excluded.withdraw()
+        Pmw.setbusycursorattributes(self.excluded.component('hull'),
+            exclude = 1)
+
+    def showAppModal(self):
+        self.dialog.activate(geometry = 'centerscreenalways')
+
+    def showGlobalModal(self):
+        self.dialog.activate(globalMode = 1)
+
+    def showDialogNoGrab(self):
+        self.dialog.activate(globalMode = 'nograb')
+
+    def showExcludedWindow(self):
+        self.excluded.show()
+
+    def execute(self, result):
+        print 'You clicked on', result
+        if result not in ('Apply', 'Help'):
+            self.dialog.deactivate(result)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/EntryField.gif b/Pmw/Pmw_1_2/doc/EntryField.gif new file mode 100644 index 00000000..d9eeb8b2 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/EntryField.gif differ diff --git a/Pmw/Pmw_1_2/doc/EntryField.html b/Pmw/Pmw_1_2/doc/EntryField.html new file mode 100644 index 00000000..5417f144 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/EntryField.html @@ -0,0 +1,545 @@ + + + + + + Pmw.EntryField reference manual + + + + +

Pmw.EntryField

+ +
+
+

Name

+

Pmw.EntryField() - + entry widget with validation +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ An entry field contains an entry widget with optional validation of + various kinds. Built-in validation may be used, such as + integer, real, time or date, or an external validation + function may be supplied. If valid text is entered, it will be + displayed with the normal background. If invalid text is entered, + it is not displayed and the previously displayed text is restored. + If partially valid text is entered, it will be displayed with a + background color to indicate it is in error. An example of + partially valid real text is '-.', which may be the first two + charactes of the valid string '-.5'. Some validators, such as + date, have a relaxed interpretation of partial validity, which + allows the user flexibility in how they enter the text.

+ +

Validation is performed early, at each keystroke or other event + which modifies the text. However, if partially valid text is + permitted, the validity of the entered text can be checked just + before it is to be used, which is a form of late validation.

+ +

Minimum and maximum values may be specified. Some validators also + accept other specifications, such as date and time formats and + separators.

+ +

+ + +
+

Validation function return values

+

+ Validation is performed by a function which takes as its first + argument the entered text and returns one of three standard + values, indicating whether the text is valid:

+ +
Pmw.OK
The text is valid.

+ +
+
Pmw.ERROR
The text is invalid and is not acceptable for + display. In this case the entry will be restored to its + previous value.

+ +
+
Pmw.PARTIAL
The text is partially valid and is acceptable + for display. In this case the text will be displayed + using the errorbackground color.

+

+ + +
+ +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
command +
+This specifies a function to call whenever the <Return> key is + pressed or invoke() is called. The default is None.

+ + +
+ +
errorbackground +
+Specifies the background color to use when displaying invalid or + partially valid text. The default is 'pink'.

+ + +
+ +
extravalidators +
+This is a dictionary of extra validators. The keys are the names + of validators which may be used in a future call to the + validate option. Each value in the dictionary is a tuple of + (validate_function, stringtovalue_function).

+

The validate_function is used to implement the validation and + the stringtovalue_function is used to convert the entry input + into a value which can be compared with the minimum and maximum + limits. These functions are as described for the validate + option.

+ +

If either of these is not given as a function, it is assumed to be + the name of one of the other extra validators or one of the + standard validators. The alias search is performed when the + validate option is configured, not when the extravalidators + option is configured or when the validate function is called.

+ +

If the name of one of the extra validators is the same as one of + the standard validators, the extra validator takes precedence. The default is {}.

+ + + +
+ +
invalidcommand +
+This is executed when invalid text is entered and the text is + restored to its previous value (that is, when the validate + function returns Pmw.ERROR). It is also called if an attempt is + made to set invalid text in a call to setentry(). The default + is self.bell.

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
modifiedcommand +
+This is called whenever the text of the entry has been changed + due to user action or by a call to setentry(). The default is None.

+ + +
+ +
sticky +
+Initialisation option. The default is 'ew'.

+ + +
+ +
validate +
+Specifies what kind of validation should be performed on the entry + input text.

+

The most general way to specify the validate option is as a + dictionary. The kind of validation is specified by the + 'validator' dictionary field, which may be the name of one of + the standard validators described below, the name of a validator + supplied by the extravalidators option, a function or None. + The default is None.

+ +

Any other dictionary fields specify other restrictions on the + entered values. For all validators, the following fields may be + specified:

+ +
'min'
Specifies the minimum acceptable value, or None if no + minimum checking should be performed. The default is None.

+ +
+
'max'
Specifies the maximum acceptable value, or None if no + maximum checking should be performed. The default is None.

+ +
+
'minstrict'
If true, then minimum checking is strictly enforced. + Otherwise, the entry input may be less than min, but will be + displayed using the errorbackground color. The default is true.

+ +
+
'maxstrict'
If true, then maximum checking is strictly enforced. + Otherwise, the entry input may be more than max, but will be + displayed using the errorbackground color. The default is true.

+ +
+

If the dictionary contains a 'stringtovalue' field, it overrides + the normal stringtovalue function for the validator. The + stringtovalue function is described below.

+ +

Other fields in the dictionary (apart from the core fields + mentioned above) are passed on to the validator and + stringtovalue functions as keyword arguments.

+ +

If validate is not a dictionary, then it is equivalent to + specifying it as a dictionary with a single 'validator' field. + For example, validate = 'real' is equivalent to /validate = + {'validator' : 'real'}/ and specifies real numbers without any + minimum or maximum limits and using '.' as the decimal point + character.

+ +

The standard validators accepted in the 'validator' field are:

+ +
'numeric'
An integer greater than or equal to 0. Digits + only. No sign.

+ +
+
'integer'
Any integer (negative, 0 or positive) as accepted + by string.atol().

+ +
+
'hexadecimal'
Hex number (with optional leading '0x'), as accepted + by string.atol(text, 16).

+ +
+
'real'
A number, with or without a decimal point and optional + exponent (e or E), as accepted by string.atof(). This + validator accepts a 'separator' argument, which specifies + the character used to represent the decimal point. The + default 'separator' is '.'.

+ +
+
'alphabetic'
Consisting of the letters 'a-z' and 'A-Z'. + In this case, 'min' and 'max' specify limits on the length + of the text.

+ +
+
'alphanumeric'
Consisting of the letters 'a-z', 'A-Z' and '0-9'. + In this case, 'min' and 'max' specify limits on the length + of the text.

+ +
+
'time'
Hours, minutes and seconds, in the format + 'HH:MM:SS', as accepted by Pmw.timestringtoseconds(). + This validator accepts a 'separator' argument, which + specifies the character used to separate the three fields. + The default separator is ':'. The time may be negative.

+ +
+
'date'
Day, month and year, as accepted by + Pmw.datestringtojdn(). This validator accepts a + 'separator' argument, which specifies the character used to + separate the three fields. The default is ':'. This + validator also accepts a 'format' argument, which is passed to + Pmw.datestringtojdn() to specify the desired ordering of the + fields. The default is 'ymd'.

+ +
+

If 'validator' is a function, then it will be called whenever + the contents of the entry may have changed due to user action or + by a call to setentry(). The function is called with at least + one argument, the first one being the new text as modified by the + user or setentry(). The other arguments are keyword arguments + made up of the non-core fields of the validate dictionary.

+ +

The validator function should return Pmw.OK, Pmw.ERROR or + Pmw.PARTIAL as described above. It should not perform minimum + and maximum checking. This is done after the call, if it returns + Pmw.OK.

+ +

The 'stringtovalue' field in the dictionary may be specified as + the name of one of the standard validators, the name of a + validator supplied by the extravalidators option, a function or + None.

+ +

The stringtovalue function is used to convert the entry input + into a value which can then be compared with any minimum or + maximum values specified for the validator. If the 'min' or + 'max' fields are specified as strings, they are converted using + the stringtovalue function. The stringtovalue function is + called with the same arguments as the validator function. The + stringtovalue function for the standard number validators + convert the string to a number. Those for the standard alpha + validators return the length of the string. Those for the + standard 'time' and 'date' validators return the number of + seconds and the Julian Day Number, respectively. See + Pmw.stringtoreal(), Pmw.timestringtoseconds() and + Pmw.datestringtojdn().

+ +

If the validator has been specified as a function and no + 'stringtovalue' field is given, then it defaults to the standard + python len() function.

+ +

If 'validator' is None, no validation is performed. However, + minimum and maximum checking may be performed, according to the + stringtovalue function. For example, to limit the entry text to + a maximum of five characters:

+ +
 Pmw.EntryField(validate = {'max' : 5})
+ +

The validator functions for each of the standard validators can + be accessed as:

+
 Pmw.numericvalidator
+ Pmw.integervalidator
+ Pmw.hexadecimalvalidator
+ Pmw.realvalidator
+ Pmw.alphabeticvalidator
+ Pmw.alphanumericvalidator
+ Pmw.timevalidator
+ Pmw.datevalidator
+ + +

Whenever the validate option is configured, the text currently + displayed in the entry widget is revalidated. If it is not valid, + the errorbackground color is set and the invalidcommand + function is called. However, the displayed text is not modified.

+ +

The default for validate is None.

+ + + +
+ +
value +
+Initialisation option. Specifies the initial contents of the entry. + If this text is invalid, it will be displayed with the + errorbackground color and the invalidcommand function will be called. + If both value and entry_textvariable options are specified in + the constructor, value will take precedence. The default is ''.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
entry +
+The widget where the user may enter text. Long text may be + scrolled horizontally by dragging with the middle mouse button. By default, this component is a Tkinter.Entry.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +In addition, methods from the +Tkinter.Entry class +are forwarded by this megawidget to the +entry component. +

+ +
checkentry()
+Check the validity of the current contents of the entry widget + and return the result. + If the text is not valid, set the background to errorbackground and + call the invalidcommand function. If there is a variable + specified by the entry_textvariable option, this method should be + called after the set() method of the variable is called. If this + is not done in this case, the entry widget background will not be + set correctly.

+ + +
+ +
clear()
+Remove all text from the entry widget. Equivalent to setentry('').

+ + +
+ +
getvalue()
+Return the text displayed by the entry.

+ + +
+ +
invoke()
+Invoke the command specified by the command option as if the + <Return> key had been pressed and return the result.

+ + +
+ +
setentry(text)
+Same as setvalue() method.

+ + +
+ +
setvalue(text)
+Set the contents of the entry widget to text and carry out + validation as if the text had been entered by the user. If the + text is invalid, the entry widget will not be changed and the + invalidcommand function will be called. Return the validity + of text.

+ + +
+ +
valid()
+Return true if the contents of the entry widget are valid.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create and pack the EntryFields.
+        self._any = Pmw.EntryField(parent,
+                labelpos = 'w',
+                label_text = 'Any:',
+                validate = None,
+                command = self.execute)
+        self._real = Pmw.EntryField(parent,
+                labelpos = 'w',
+                value = '55.5',
+                label_text = 'Real (10.0 to 99.0):',
+                validate = {'validator' : 'real',
+                        'min' : 10, 'max' : 99, 'minstrict' : 0},
+                modifiedcommand = self.changed)
+        self._odd = Pmw.EntryField(parent,
+                labelpos = 'w',
+                label_text = 'Odd length:',
+                validate = self.custom_validate,
+                value = 'ABC')
+        self._date = Pmw.EntryField(parent,
+                labelpos = 'w',
+                label_text = 'Date (in 2000):',
+                value = '2000/2/29',
+                validate = {'validator' : 'date',
+                        'min' : '2000/1/1', 'max' : '2000/12/31',
+                        'minstrict' : 0, 'maxstrict' : 0,
+                        'format' : 'ymd'},
+                )
+        now = time.localtime(time.time())
+        self._date2 = Pmw.EntryField(parent,
+                labelpos = 'w',
+                label_text = 'Date (d.m.y):',
+                value = '%d.%d.%d' % (now[2], now[1], now[0]),
+                validate = {'validator' : 'date',
+                        'format' : 'dmy', 'separator' : '.'},
+                )
+        self._time = Pmw.EntryField(parent,
+                labelpos = 'w',
+                label_text = 'Time (24hr clock):',
+                value = '8:00:00',
+                validate = {'validator' : 'time',
+                        'min' : '00:00:00', 'max' : '23:59:59',
+                        'minstrict' : 0, 'maxstrict' : 0},
+                )
+        self._comma = Pmw.EntryField(parent,
+                labelpos = 'w',
+                label_text = 'Real (with comma):',
+                value = '123,456',
+                validate = {'validator' : 'real', 'separator' : ','},
+                )
+
+        entries = (self._any, self._real, self._odd, self._date, self._date2,
+                self._time, self._comma)
+
+        for entry in entries:
+            entry.pack(fill='x', expand=1, padx=10, pady=5)
+        Pmw.alignlabels(entries)
+
+        self._any.component('entry').focus_set()
+
+    def changed(self):
+        print 'Text changed, value is', self._real.getvalue()
+
+    def execute(self):
+        print 'Return pressed, value is', self._any.getvalue()
+
+    # This implements a custom validation routine.  It simply checks
+    # if the string is of odd length.
+    def custom_validate(self, text):
+        print 'text:', text
+        if len(text) % 2 == 0:
+          return -1
+        else:
+          return 1
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 22 May 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ExampleDemo.py b/Pmw/Pmw_1_2/doc/ExampleDemo.py new file mode 100644 index 00000000..f7ec1e71 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ExampleDemo.py @@ -0,0 +1,33 @@ +title = 'Pmw.EXAMPLE demonstration' + +# Import Pmw from this directory tree. +import sys +sys.path[:0] = ['../../..'] + +import Tkinter +import Pmw + +class Demo: + def __init__(self, parent): + + # Create and pack the EXAMPLEs. + self.widget1 = Pmw.Counter(parent) + self.widget1.setentry('1') + self.widget1.pack() + + self.widget2 = Pmw.Counter(parent, increment = 10) + self.widget2.setentry('100') + self.widget2.pack() + +###################################################################### + +# Create demo in root window for testing. +if __name__ == '__main__': + root = Tkinter.Tk() + Pmw.initialise(root) + root.title(title) + + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy) + exitButton.pack(side = 'bottom') + widget = Demo(root) + root.mainloop() diff --git a/Pmw/Pmw_1_2/doc/Group.gif b/Pmw/Pmw_1_2/doc/Group.gif new file mode 100644 index 00000000..9c4d8d5e Binary files /dev/null and b/Pmw/Pmw_1_2/doc/Group.gif differ diff --git a/Pmw/Pmw_1_2/doc/Group.html b/Pmw/Pmw_1_2/doc/Group.html new file mode 100644 index 00000000..b961a1f2 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/Group.html @@ -0,0 +1,226 @@ + + + + + + Pmw.Group reference manual + + + + +

Pmw.Group

+ +
+
+

Name

+

Pmw.Group() - + frame with ring border and tag +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ This megawidget consists of an interior frame with an exterior + ring border and an identifying tag displayed over the top edge of + the ring. The programmer can create other widgets within the + interior frame.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
collapsedsize +
+Initialisation option. The distance from the bottom of the tag to the bottom of the ring + when the groupchildsite is collapsed. The default is 6.

+ + +
+ +
tagindent +
+Initialisation option. The distance from the left edge of the ring to the left side of + the tag component. The default is 10.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
groupchildsite +
+The frame which can contain other widgets to be grouped. By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
ring +
+This component acts as the enclosing ring around the + groupchildsite. The default borderwidth is 2 and the + default relief is 'groove'. By default, this component is a Tkinter.Frame.

+ + +
+ +
tag +
+The identifying tag displayed over the top edge of the enclosing + ring. If the pyclass for this component is None, (ie: + tag_pyclass = None, then no tag component is created. By default, this component is a Tkinter.Label.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
collapse()
+Do not display the groupchildsite component.

+ + +
+ +
expand()
+Display the groupchildsite component.

+ + +
+ +
interior()
+Return the frame within which the programmer may create widgets. + This is the same as component('groupchildsite').

+ + +
+ +
toggle()
+Display the groupchildsite component if it is currently hidden and + hide it if it is currently displayed.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+
+        # Create and pack the Groups.
+        w = Pmw.Group(parent, tag_text='label')
+        w.pack(fill = 'both', expand = 1, padx = 6, pady = 6)
+        cw = Tkinter.Label(w.interior(),
+                text = 'A group with the\ndefault Label tag')
+        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
+
+        w = Pmw.Group(parent, tag_pyclass = None)
+        w.pack(fill = 'both', expand = 1, padx = 6, pady = 6)
+        cw = Tkinter.Label(w.interior(), text = 'A group\nwithout a tag')
+        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
+
+        radiogroups = []
+        self.var = Tkinter.IntVar()
+        self.var.set(0)
+        radioframe = Tkinter.Frame(parent)
+        w = Pmw.Group(radioframe,
+                tag_pyclass = Tkinter.Radiobutton,
+                tag_text='radiobutton 1',
+                tag_value = 0,
+                tag_variable = self.var)
+        w.pack(fill = 'both', expand = 1, side='left')
+        cw = Tkinter.Frame(w.interior(),width=200,height=20)
+        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
+        radiogroups.append(w)
+
+        w = Pmw.Group(radioframe,
+                tag_pyclass = Tkinter.Radiobutton,
+                tag_text='radiobutton 2',
+                tag_font = Pmw.logicalfont('Helvetica', 4),
+                tag_value = 1,
+                tag_variable = self.var)
+        w.pack(fill = 'both', expand = 1, side='left')
+        cw = Tkinter.Frame(w.interior(),width=200,height=20)
+        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
+        radiogroups.append(w)
+        radioframe.pack(padx = 6, pady = 6, expand='yes', fill='both')
+        Pmw.aligngrouptags(radiogroups)
+
+        w = Pmw.Group(parent,
+                tag_pyclass = Tkinter.Checkbutton,
+                tag_text='checkbutton',
+                tag_foreground='blue')
+        w.pack(fill = 'both', expand = 1, padx = 6, pady = 6)
+        cw = Tkinter.Frame(w.interior(),width=150,height=20)
+        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
+
+        w = Pmw.Group(parent,
+                tag_pyclass = Tkinter.Button,
+                tag_text='Tkinter.Button')
+        w.configure(tag_command = w.toggle)
+        w.pack(fill = 'both', expand = 1, padx = 6, pady = 6)
+        cw = Tkinter.Label(w.interior(),
+                background = 'aliceblue',
+                text = 'A group with\na Button tag!?'
+        )
+        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
+
+        w = Pmw.Group(parent,
+                tag_pyclass = Tkinter.Button,
+                tag_text='Show/Hide')
+        w.configure(tag_command = w.toggle)
+        w.pack(fill = 'both', expand = 1, padx = 6, pady = 6)
+        cw = Tkinter.Label(w.interior(),
+                background = 'aliceblue',
+                text = 'Now you see me.\nNow you don\'t.'
+        )
+        cw.pack(padx = 2, pady = 2, expand='yes', fill='both')
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 15 November 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/HistoryText.gif b/Pmw/Pmw_1_2/doc/HistoryText.gif new file mode 100644 index 00000000..5ee3ae37 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/HistoryText.gif differ diff --git a/Pmw/Pmw_1_2/doc/HistoryText.html b/Pmw/Pmw_1_2/doc/HistoryText.html new file mode 100644 index 00000000..c42dad64 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/HistoryText.html @@ -0,0 +1,427 @@ + + + + + + Pmw.HistoryText reference manual + + + + +

Pmw.HistoryText

+ +
+
+

Name

+

Pmw.HistoryText() - + text widget with a course-grained form of history +

+ + +
+

Inherits

+Pmw.ScrolledText
+
+

Description

+

+ A history text is a scrolled text widget with added functionality + to maintain a history of each screen and allow editing of prior + screens. Here, screen refers to the entire contents of the text + widget. This widget does not support a fine-grained history of + every change made to the text.

+ +

Together with a few buttons and a scrolled text to display the + results, a history text can be used as the query-entry part of a + simple interactive text-based database query system. When the + user enters and executes a query, the query (the entire contents + of the text widget) is added to the history list. The user may + view previous queries and either execute them again or modify them + and execute the new query. If a previously executed query is + modified, the user may undo or redo all changes made to the query + before the query is executed.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
borderframe +
+Initialisation option. If true, the borderframe component will be created. The default is 0.

+ + +
+ +
columnheader +
+Initialisation option. If true, the columnheader component will be created. The default is 0.

+ + +
+ +
compressany +
+See addhistory(). The default is 1.

+ + +
+ +
compresstail +
+See addhistory(). The default is 1.

+ + +
+ +
historycommand +
+This is a callback to indicate whether the currently displayed + entry in the history list has a previous or next entry. The + callback is given two arguments, prevstate and nextstate. If + the currently displayed entry is first in the history list, then + prevstate is 'disabled', otherwise it is 'normal'. If the + currently displayed entry is last in the history list, then + nextstate is 'disabled', otherwise it is 'normal'. These + values can be used, for example, to modify the state of Next and + Previous buttons that call the next() and prev() methods. The default is None.

+ + +
+ +
hscrollmode +
+The horizontal scroll mode. If 'none', the horizontal scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
rowcolumnheader +
+Initialisation option. If true, the rowcolumnheader component will be created. The default is 0.

+ + +
+ +
rowheader +
+Initialisation option. If true, the rowheader component will be created. The default is 0.

+ + +
+ +
scrollmargin +
+Initialisation option. The distance between the scrollbars and the text widget. The default is 2.

+ + +
+ +
usehullsize +
+Initialisation option. If true, the size of the megawidget is determined solely by the + width and height options of the hull component.

+

Otherwise, the size of the megawidget is determined by the width + and height of the text component, along with the size and/or + existence of the other components, such as the label, the + scrollbars and the scrollmargin option. All these affect the + overall size of the megawidget. The default is 0.

+ + + +
+ +
vscrollmode +
+The vertical scroll mode. If 'none', the vertical scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
borderframe +
+A frame widget which snuggly fits around the text widget, to give + the appearance of a text border. It is created with a border so + that the text widget, which is created without a border, looks + like it has a border. By default, this component is a Tkinter.Frame.

+ + +
+ +
columnheader +
+A text widget with a default height of 1 displayed above the main + text widget and which scrolls horizontally in sync with the + horizontal scrolling of the main text widget. By default, this component is a Tkinter.Text. Its component group is Header.

+ + +
+ +
horizscrollbar +
+The horizontal scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
rowcolumnheader +
+A text widget displayed to the top left of the main text widget, + above the row header and to the left of the column header if they + exist. The widget is not scrolled automatically. By default, this component is a Tkinter.Text. Its component group is Header.

+ + +
+ +
rowheader +
+A text widget displayed to the left of the main text widget and + which scrolls vertically in sync with the vertical scrolling of + the main text widget. By default, this component is a Tkinter.Text. Its component group is Header.

+ + +
+ +
text +
+The text widget which is scrolled by the scrollbars. If the + borderframe option is true, this is created with a borderwidth + of 0 to overcome a known problem with text widgets: if a widget + inside a text widget extends across one of the edges of the text + widget, then the widget obscures the border of the text widget. + Therefore, if the text widget has no border, then this overlapping + does not occur. By default, this component is a Tkinter.Text.

+ + +
+ +
vertscrollbar +
+The vertical scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.ScrolledText. +

+ +
addhistory()
+Append the currently displayed text to the history list.

+

If compressany is true, a new entry will be added to the history + list only if the currently displayed entry has changed.

+ +

If compresstail is true, a new entry will be added to the + history list only if the currently displayed entry has changed + or if it is not the last entry in the history list.

+ + + +
+ +
gethistory()
+Return the history list. Each entry in the list is a 3-tuple. + The first item in a history entry is the original text as added by + addhistory(). The second item is the edited text (if the user + has modified the entry but addhistory() has not yet been called + on the text). The third item specifies whether the entry should + currently display the original or modified text.

+ + +
+ +
next()
+Display the next screen in the history list.

+ + +
+ +
prev()
+Display the previous screen in the history list.

+ + +
+ +
redo()
+Reverse the effect of undo().

+ + +
+ +
undo()
+Undo all changes made since this entry was added to the history + list.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create and pack the PanedWidget to hold the query and result
+        # windows.
+        # !! panedwidget should automatically size to requested size
+        panedWidget = Pmw.PanedWidget(parent,
+                orient = 'vertical',
+                hull_height = 400,
+                hull_width = 550)
+        panedWidget.add('query', min = 0.05, size = 0.2)
+        panedWidget.add('buttons', min = 0.1, max = 0.1)
+        panedWidget.add('results', min = 0.05)
+        panedWidget.pack(fill = 'both', expand = 1)
+
+        # Create and pack the HistoryText.
+        self.historyText = Pmw.HistoryText(panedWidget.pane('query'),
+                text_wrap = 'none',
+                text_width = 60,
+                text_height = 10,
+                historycommand = self.statechange,
+        )
+        self.historyText.pack(fill = 'both', expand = 1)
+        self.historyText.component('text').focus()
+
+        buttonList = (
+            [20, None],
+            ['Clear', self.clear],
+            ['Undo', self.historyText.undo],
+            ['Redo', self.historyText.redo],
+            [20, None],
+            ['Prev', self.historyText.prev],
+            ['Next', self.historyText.next],
+            [30, None],
+            ['Execute', Pmw.busycallback(self.executeQuery)],
+        )
+        self.buttonDict = {}
+
+        buttonFrame = panedWidget.pane('buttons')
+        for text, cmd in buttonList:
+            if type(text) == type(69):
+                frame = Tkinter.Frame(buttonFrame, width = text)
+                frame.pack(side = 'left')
+            else:
+                button = Tkinter.Button(buttonFrame, text = text, command = cmd)
+                button.pack(side = 'left')
+                self.buttonDict[text] = button
+
+        for text in ('Prev', 'Next'):
+            self.buttonDict[text].configure(state = 'disabled')
+
+        self.results = Pmw.ScrolledText(panedWidget.pane('results'), text_wrap = 'none')
+        self.results.pack(fill = 'both', expand = 1)
+
+    def statechange(self, prevstate, nextstate):
+        self.buttonDict['Prev'].configure(state = prevstate)
+        self.buttonDict['Next'].configure(state = nextstate)
+
+    def clear(self):
+        self.historyText.delete('1.0', 'end')
+
+    def addnewlines(self, text):
+        if len(text) == 1:
+            text = text + '\n'
+        if text[-1] != '\n':
+            text = text + '\n'
+        if text[-2] != '\n':
+            text = text + '\n'
+        return text
+
+    def executeQuery(self):
+        sql = self.historyText.get()
+        self.results.insert('end', 'Query:\n' + self.addnewlines(sql))
+        self.results.see('end')
+        self.results.update_idletasks()
+        self.historyText.addhistory()
+        results = 'Results:\nfoo'
+        if len(results) > 0:
+            self.results.insert('end', self.addnewlines(results))
+        self.results.see('end')
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 20 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/LabeledWidget.gif b/Pmw/Pmw_1_2/doc/LabeledWidget.gif new file mode 100644 index 00000000..dfa61540 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/LabeledWidget.gif differ diff --git a/Pmw/Pmw_1_2/doc/LabeledWidget.html b/Pmw/Pmw_1_2/doc/LabeledWidget.html new file mode 100644 index 00000000..726ba08f --- /dev/null +++ b/Pmw/Pmw_1_2/doc/LabeledWidget.html @@ -0,0 +1,170 @@ + + + + + + Pmw.LabeledWidget reference manual + + + + +

Pmw.LabeledWidget

+ +
+
+

Name

+

Pmw.LabeledWidget() - + frame with label +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ This megawidget consists of an interior frame with an associated + label which can be positioned on any side of the frame. The + programmer can create other widgets within the interior frame.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
sticky +
+Initialisation option. The default is 'nsew'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
labelchildsite +
+The frame which can contain other widgets to be labelled. By default, this component is a Tkinter.Frame.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
interior()
+Return the frame within which the programmer may create widgets. + This is the same as component('labelchildsite').

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+
+        # Create a frame to put the LabeledWidgets into
+        frame = Tkinter.Frame(parent, background = 'grey90')
+        frame.pack(fill = 'both', expand = 1)
+
+        # Create and pack the LabeledWidgets.
+        column = 0
+        row = 0
+        for pos in ('n', 'nw', 'wn', 'w'):
+            lw = Pmw.LabeledWidget(frame,
+                    labelpos = pos,
+                    label_text = pos + ' label')
+            lw.component('hull').configure(relief='sunken', borderwidth=2)
+            lw.grid(column=column, row=row, padx=10, pady=10)
+            cw = Tkinter.Button(lw.interior(), text='child\nsite')
+            cw.pack(padx=10, pady=10, expand='yes', fill='both')
+
+            # Get ready for next grid position.
+            column = column + 1
+            if column == 2:
+              column = 0
+              row = row + 1
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 8 November 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/MainMenuBar.gif b/Pmw/Pmw_1_2/doc/MainMenuBar.gif new file mode 100644 index 00000000..aa7a7bf8 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/MainMenuBar.gif differ diff --git a/Pmw/Pmw_1_2/doc/MainMenuBar.html b/Pmw/Pmw_1_2/doc/MainMenuBar.html new file mode 100644 index 00000000..4f0fea88 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/MainMenuBar.html @@ -0,0 +1,421 @@ + + + + + + Pmw.MainMenuBar reference manual + + + + +

Pmw.MainMenuBar

+ +
+
+

Name

+

Pmw.MainMenuBar() - + manager for toplevel native menus +

+ + +
+

Inherits

+Pmw.MegaArchetype
+
+

Description

+

+ This class is a wrapper for the Tkinter.Menu class. It should be + used as the main menu of toplevel windows. The class is similar + to Pmw.MenuBar, but should be used when native menus are required. + See the Tkinter.Menu documentation for full details.

+ +

This class should be created as the child of a Tkinter.Toplevel + and should then be specified as the menu associated with the + toplevel, using the toplevel's configure() method. For example:

+
 # Create a Pmw.MegaToplevel.
+ megaToplevel = Pmw.MegaToplevel()
+ # Get the Tkinter.Toplevel from Pmw.MegaToplevel.
+ toplevel = megaToplevel.interior()
+ # Create the menu bar for the toplevel.
+ menuBar = Pmw.MainMenuBar(toplevel)
+ # Configure the toplevel to use the menuBar.
+ toplevel.configure(menu = menuBar)
+ + +

There are methods to add menus, both as toplevel menus and + sub-menus, and for adding menu items to the menus. Each menu item + may have help text to be displayed by a Pmw.Balloon. Each menu and + cascaded menu (sub-menu) is referenced by name which is supplied + on creation.

+ +

This megawidget is derived from Pmw.MegaArchetype (not Pmw.MegaWidget + like most other megawidgets), with the hull class being + Tkinter.Menu.

+ +

(Note that due to bugs in Tk's menubar functionality, balloon help + has not been implemented and status help does not work properly.)

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
balloon +
+Specifies a Pmw.Balloon to display the help text for menu items. If + None, no help is displayed. If the balloon has an associated + Pmw.MessageBar, the help text will also be displayed there.

+

Due to a bug in some versions of Tk (8.0 and possible others), + help text will not be displayed by the balloon. However, help + text will be displayed in the balloon's associated messagebar. The default is None.

+ + + +
+ +
hotkeys +
+Initialisation option. If true, keyboard accelerators will be assigned to each menu item. + Keyboard accelerators can be used to access the menus without + using the mouse. The accelerator character is always one of the + alphanumeric characters in the text label of the menu item and is + indicated by an underline.

+

To select a menu, simultaneously press the <Alt> key and the + accelerator character indicated on a toplevel menu item. The + arrows keys can then be used to select other menus and menu items. + To invoke a menu item, press <Return> or press the accelerator + character indicated on the menu item.

+ +

Each accelerator character will be assigned automatically unless + traverseSpec is supplied to the addmenu(), addmenuitem() or + addcascademenu() methods. The automatically selected + accelerator character for a menu item is the first character in + the label text that has not already been used as an accelerator in + the menu containing the menu item.

+ +

If traverseSpec is given, it must be either an integer or a + character. If an integer, it specifies the index of the character + in the label text to use as the accelerator character. If a + character, it specifies the character to use as the accelerator + character. The default is 1.

+ + + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+The toplevel menu widget. By default, this component is a Tkinter.Menu.

+ + +
+
+

Dynamic components

+

+ Menu components are created dynamically by the addmenu() and + addcascademenu() methods. By default, these are of type + Tkinter.Menu and are created with a component group of Menu.

+

+ + + +
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaArchetype. +In addition, methods from the +Tkinter.Menu class +are forwarded by this megawidget to the +hull component. +

+ +
addcascademenu(parentMenuName, menuName, statusHelp = '', traverseSpec = None, **kw)
+Add a cascade menu (sub-menu) to the menu parentMenuName. The + menuName argument must not be the same as any menu already + created using the addmenu() or addcascademenu() methods.

+

A menu item in the parent menu is created (with the + add_cascade() method of the parent menu) using all keyword + arguments except tearoff and name.

+ +

If the label keyword argument is not given, the label option + of the menu item defaults to menuName. If the underline + keyword argument is not given (and the hotkeys megawidget option + is true) the underline option is determined as described under + hotkeys and is used to specify the keyboard accelerator.

+ +

The statusHelp argument is used as the help string for the menu + item. This is displayed using the showstatus() method of the + balloon.

+ +

The tearoff and name keyword arguments, if present, are passed + to the constructor of the menu. See Tkinter.Menu for details of + these options. The menu is created as a component named + menuName.

+ + + +
+ +
addmenu(menuName, balloonHelp, statusHelp = None, traverseSpec = None, **kw)
+Add a cascade menu to the toplevel menu. The menuName argument + must not be the same as any menu already created using the + addmenu() or addcascademenu() methods.

+

A menu item in the toplevel menu is created (with the + add_cascade() method) using all keyword arguments except + tearoff and name.

+ +

If the label keyword argument is not given, the label option + of the menu button defaults to menuName. If the underline + keyword argument is not given (and the hotkeys megawidget option + is true) the underline option is determined as described under + hotkeys and is used to specify the keyboard accelerator.

+ +

The statusHelp argument is used as the help string for the menu + item. This is displayed using the showstatus() method of the + balloon. Currently balloonHelp is not used, due to a bug in Tk + version 8.0.

+ +

The tearoff and name keyword arguments, if present, are passed + to the constructor of the menu. See Tkinter.Menu for details of + these options. The menu is created as a component named + menuName.

+ + + +
+ +
addmenuitem(menuName, itemType, statusHelp = '', traverseSpec = None, **kw)
+Add a menu item to the menu menuName. The kind of menu item is + given by itemType and may be one of command, separator, + checkbutton, radiobutton or cascade (although cascade menus + are better added using the addcascademenu() method). Any + keyword arguments present will be passed to the menu when creating + the menu item. See Tkinter.Menu for the valid options for each + item type. In addition, a keyboard accelerator may be + automatically given to the item, as described under hotkeys.

+

When the mouse is moved over the menu item, the helpString will + be displayed by the balloon's statuscommand.

+ + + +
+ +
deletemenu(menuName)
+Delete the menu menuName and all its items. The menu may either + be a toplevel menu or a cascade menu.

+ + +
+ +
deletemenuitems(menuName, start, end = None)
+Delete menu items from the menu menuName. If end is not + given, the start item is deleted. Otherwise all items from + start to end are deleted.

+ + +
+ +
disableall()
+Disable all toplevel menus.

+ + +
+ +
enableall()
+Enable all toplevel menus.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create button to launch the toplevel with main menubar.
+        w = Tkinter.Button(parent, text = 'Show Pmw.MainMenuBar demo',
+                command = lambda parent=parent: MainMenuBarToplevel(parent))
+        w.pack(padx = 8, pady = 8)
+
+class MainMenuBarToplevel:
+    def __init__(self, parent):
+        # Create the toplevel to contain the main menubar.
+        megaToplevel = Pmw.MegaToplevel(parent, title = title)
+        toplevel = megaToplevel.interior()
+
+        # Create the Balloon for this toplevel.
+        self.balloon = Pmw.Balloon(toplevel)
+
+        # Create and install the MenuBar.
+        menuBar = Pmw.MainMenuBar(toplevel,
+                balloon = self.balloon)
+        toplevel.configure(menu = menuBar)
+        self.menuBar = menuBar
+
+        # Add some buttons to the MainMenuBar.
+        menuBar.addmenu('File', 'Close this window or exit')
+        menuBar.addmenuitem('File', 'command', 'Close this window',
+                command = PrintOne('Action: close'),
+                label = 'Close')
+        menuBar.addmenuitem('File', 'separator')
+        menuBar.addmenuitem('File', 'command', 'Exit the application',
+                command = PrintOne('Action: exit'),
+                label = 'Exit')
+
+        menuBar.addmenu('Edit', 'Cut, copy or paste')
+        menuBar.addmenuitem('Edit', 'command', 'Delete the current selection',
+                command = PrintOne('Action: delete'),
+                label = 'Delete')
+
+        menuBar.addmenu('Options', 'Set user preferences')
+        menuBar.addmenuitem('Options', 'command', 'Set general preferences',
+                command = PrintOne('Action: general options'),
+                label = 'General...')
+
+        # Create a checkbutton menu item.
+        self.toggleVar = Tkinter.IntVar()
+        # Initialise the checkbutton to 1:
+        self.toggleVar.set(1)
+        menuBar.addmenuitem('Options', 'checkbutton', 'Toggle me on/off',
+                label = 'Toggle',
+                command = self._toggleMe,
+                variable = self.toggleVar)
+        self._toggleMe()
+
+        menuBar.addcascademenu('Options', 'Size',
+                'Set some other preferences', traverseSpec = 'z', tearoff = 1)
+        for size in ('tiny', 'small', 'average', 'big', 'huge'):
+            menuBar.addmenuitem('Size', 'command', 'Set size to ' + size,
+                    command = PrintOne('Action: size ' + size),
+                    label = size)
+
+        menuBar.addmenu('Help', 'User manuals', name = 'help')
+        menuBar.addmenuitem('Help', 'command', 'About this application',
+                command = PrintOne('Action: about'),
+                label = 'About...')
+
+        # Create and pack the main part of the window.
+        self.mainPart = Tkinter.Label(toplevel,
+                text = 'This is the\nmain part of\nthe window',
+                background = 'black',
+                foreground = 'white',
+                padx = 30,
+                pady = 30)
+        self.mainPart.pack(fill = 'both', expand = 1)
+
+        # Create and pack the MessageBar.
+        self.messageBar = Pmw.MessageBar(toplevel,
+                entry_width = 40,
+                entry_relief='groove',
+                labelpos = 'w',
+                label_text = 'Status:')
+        self.messageBar.pack(fill = 'x', padx = 10, pady = 10)
+        self.messageBar.message('state',
+            'Balloon/status help not working properly - Tk menubar bug')
+
+        buttonBox = Pmw.ButtonBox(toplevel)
+        buttonBox.pack(fill = 'x')
+        buttonBox.add('Disable\nall', command = menuBar.disableall)
+        buttonBox.add('Enable\nall', command = menuBar.enableall)
+        buttonBox.add('Create\nmenu', command = self.add)
+        buttonBox.add('Delete\nmenu', command = self.delete)
+        buttonBox.add('Create\nitem', command = self.additem)
+        buttonBox.add('Delete\nitem', command = self.deleteitem)
+
+        # Configure the balloon to displays its status messages in the
+        # message bar.
+        self.balloon.configure(statuscommand = self.messageBar.helpmessage)
+
+        self.testMenuList = []
+
+    def _toggleMe(self):
+        print 'Toggle value:', self.toggleVar.get()
+
+    def add(self):
+        if len(self.testMenuList) == 0:
+            num = 0
+        else:
+            num = self.testMenuList[-1]
+        num = num + 1
+        name = 'Menu%d' % num
+        self.testMenuList.append(num)
+
+        self.menuBar.addmenu(name, 'This is ' + name)
+
+    def delete(self):
+        if len(self.testMenuList) == 0:
+            self.menuBar.bell()
+        else:
+            num = self.testMenuList[0]
+            name = 'Menu%d' % num
+            del self.testMenuList[0]
+            self.menuBar.deletemenu(name)
+
+    def additem(self):
+        if len(self.testMenuList) == 0:
+            self.menuBar.bell()
+        else:
+            num = self.testMenuList[-1]
+            menuName = 'Menu%d' % num
+            menu = self.menuBar.component(menuName)
+            if menu.index('end') is None:
+                label = 'item X'
+            else:
+                label = menu.entrycget('end', 'label') + 'X'
+            self.menuBar.addmenuitem(menuName, 'command', 'Help for ' + label,
+                    command = PrintOne('Action: ' + menuName + ': ' + label),
+                    label = label)
+            
+    def deleteitem(self):
+        if len(self.testMenuList) == 0:
+            self.menuBar.bell()
+        else:
+            num = self.testMenuList[-1]
+            menuName = 'Menu%d' % num
+            menu = self.menuBar.component(menuName)
+            if menu.index('end') is None:
+                self.menuBar.bell()
+            else:
+                self.menuBar.deletemenuitems(menuName, 0)
+            
+class PrintOne:
+    def __init__(self, text):
+        self.text = text
+
+    def __call__(self):
+        print self.text
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 22 April 2000 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/MegaArchetype.html b/Pmw/Pmw_1_2/doc/MegaArchetype.html new file mode 100644 index 00000000..03f62660 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/MegaArchetype.html @@ -0,0 +1,459 @@ + + + + + + Pmw.MegaArchetype reference manual + + + + +

Pmw.MegaArchetype

+ +
+

Name

+

Pmw.MegaArchetype() - + abstract base class for all Pmw megawidgets +

+ + +
+

Description

+

+ This class is the basis for all Pmw megawidgets. It provides + methods to manage options and component widgets.

+ +

This class is normally used as a base class for other classes. If + the hullClass argument is specified, such as in the Pmw.MegaWidget + and Pmw.MegaToplevel classes, a container widget is created to act + as the parent of all other component widgets. Classes derived + from these sub classes create other component widgets and options + to implement megawidgets that can be used in applications.

+ +

If no hullClass argument is given to the constructor, no + container widget is created and only the option configuration + functionality is available.

+ +

+ + +
+

Components

+

+ A megawidget is generally made up of other widgets packed + within the megawidget's containing widget. These sub-widgets + are called the components of the megawidget and are given + logical names for easy reference. The component mechanism + allows the user of a megawidget to gain controlled access to + some of the internals of the megawidget, for example to call a + method of a component or to set a component's configuration + options.

+ +

Sub components: If a component is itself a megawidget containing + sub-components, then these sub-components can be referred to + using the notation component_subcomponent. For example, + Pmw.ComboBox has a component named entryfield which is an + instance of Pmw.EntryField, which itself has a Tkinter.Entry + component named entry. In the context of the combobox, this + entry widget can be referred to as entryfield_entry.

+ +

Component aliases: Because the sub-component notation may + make component names inconveniently long, components and + sub-components can be aliased to simpler names. For example, + the entryfield_entry sub-component of Pmw.ComboBox is aliased + to simply entry. If there is no conflict in component + names, sub-component names are usually aliased to the name of + the "leaf" component.

+ +

Component groups: Similar components of a megawidget can be + given a group name, which allows all components of a group + to be referenced using the one group name. For example, the + two arrow components of Pmw.Counter have a group name of Arrow. + Also, megawidgets that can create an unlimited number of + similar components, such as Pmw.ButtonBox, create each of these + components with the same group name. By convention, group + names begin with a capital letter.

+

+ + + +
+

Options

+

+ A megawidget defines options which allow the megawidget user + to modify the appearance and behaviour of the megawidget. + Using the same technique as Tkinter widgets, the values of + megawidget options may be set in calls to the constructor and + to configure() and the values may be queried by calls to + cget() and configure(). Like Tkinter widgets, megawidget + options are initialised with default values. Also, if the + useTkOptionDb option to Pmw.initialise() has been set, + then the Tk option database will be queried to get the initial + values. Strings found in the option database are converted + to python objects (integer, float, tuple, dictionary, etc) + using a restricted eval() call. Anything that is not accepted by + eval() is treated as a string.

+ +

Inherited options: As well as the options defined in a class, + a derived class inherits all options of its base classes. The + default value of an option defined by a base class may be + modified by the derived class.

+ +

Initialisation options: Some megawidget options can only be + set in the call to the constructor. These are called + initialisation options. Unlike normal configuration + options, they cannot be set by calling the configure() + method.

+ +

Component options: Options of the components of a megawidget + can be referred to using the notation component_option. + Like the megawidget options, component options can be used in + calls to the constructor and to the cget() and configure() + methods. For example, the state option of the Tkinter.Text + text component of Pmw.ScrolledText may be set by calling

+
 widget.configure(text_state = 'disabled')
+ + +

Sub-components, component aliases and component groups may + also be combined with options. For example, the state + option of the entryfield_entry component of Pmw.ComboBox + may be set by calling

+
 combobox.configure(entryfield_entry_state = 'normal')
+ + +

Since it has an alias, it is more convenient to use the + equivalent form

+
 combobox.configure(entry_state = 'normal')
+ + +

Also, the background color of both arrows of Pmw.Counter + can be set using the Arrow component group.

+
 counter.configure(Arrow_background = 'aliceblue')
+ + +

+ + +
+

The pyclass component option

+

+ The pyclass component option is a special notation that can + be used to specify a non-default python class for a component. + This can only be used when the component is being constructed. + For a component created during the construction of its parent + megawidget, this option must be given to the constructor in + the form component_pyclass. For example, to change the + python class of the text sub-component of Pmw.TextDialog + to a class FontText.Text

+
 dialog = Pmw.TextDialog(text_pyclass = FontText.Text)
+ + +

For components created after the construction of the parent + megawidget, the pyclass option must be passed into the + method which constructs the component. For example, to set + the python class of a button in Pmw.ButtonBox to a class + MyButton:

+
 buttonBox.add('special', pyclass = MyButton)
+ + +

The new python class of the component must support all methods + and options that are used by the megawidget when operating on + the component. The exact interface required for each + component is not documented. You will have to examine the Pmw + source code. However, any class derived from the default + class of a component can be used as the new class of the + component, as long as all of the original methods and options + are still supported. For example, any class derived from + Tkinter.Text can be used as the class of the text + sub-component of Pmw.TextDialog.

+ +

The pyclass component option should not be confused with the + class option that some of the Tk widgets support. The + class option sets the Tk option database class for the + widget and is used by Tk to query the database for the default + values of the widget's other options. The name pyclass was + chosen so that it did not conflict with any known Tk options.

+ +

+ + +
+

Construction

+

+ The constructors of classes derived from this class all accept + the same arguments: one positional argument and any number of + keyword arguments. The positional argument defaults to None + (meaning the root window) and specifies the widget to use as + the parent when creating the + megawidget's hull component. The keyword arguments define + initial values for options. The format for the constructors + of derived classes is:

+ +
   def __init__(self, parent = None, **kw):
+

+ + + +
+ +

Methods

+ +
addoptions(optionDefs)
+Add additional options for this megawidget. The optionDefs + argument is treated in the same way as for the defineoptions() + method.

+

This method is for use by derived classes. It is only used if a + megawidget should conditionally define some options, perhaps + depending on the value of other options. Usually, megawidgets + unconditionally define all their options in the call to + defineoptions() and do not need to use addoptions(). This + method must be called after the call to defineoptions() and + before the call to initialiseoptions().

+ + + +
+ +
cget(option)
+Return the current value of option (which should be in the + format described in the Options section). This method is also + available using object subscripting, for example + myWidget['font']. Unlike Tkinter's cget(), which always returns + a string, this method returns the same value and type as used when + the option was set (except where option is a component option + and the component is a Tkinter widget, in which case it returns + the string returned by Tcl/Tk).

+ + +
+ +
component(name)
+Return the component widget whose name is name. This + allows the user of a megawidget to access and configure component + widgets directly.

+ + +
+ +
componentaliases()
+Return the list of aliases for components. Each item in the list + is a tuple whose first item is the name of the alias and whose + second item is the name of the component or sub-component it + refers to.

+ + +
+ +
componentgroup(name)
+Return the group of the component whose name is name or None + if it does not have a group.

+ + +
+ +
components()
+Return a sorted list of names of the components of this + megawidget.

+ + +
+ +
configure(option = None, **kw)
+Query or configure the megawidget options.

+

If no arguments are given, return a tuple consisting of all + megawidget options and values, each as a 5-element tuple + (name, resourceName, resourceClass, default, value). + This is in the same format as the value returned by the standard + Tkinter configure() method, except that the resource name is + always the same as the option name and the resource class is the + option name with the first letter capitalised.

+ +

If one argument is given, return the 5 element tuple for option.

+ +

Otherwise, set the configuration options specified by the keyword + arguments. Each key should be in the format described in the + Options section.

+ + + +
+ +
createcomponent(componentName, componentAliases, componentGroup, widgetClass, *widgetArgs, **kw)
+Create a component widget by calling widgetClass with the + arguments given by widgetArgs and any keyword arguments. The + componentName argument is the name by which the component will + be known and must not contain the underscore, '_', character. + The componentGroup argument specifies the group of the + component. The componentAliases argument is a sequence of + 2-element tuples, whose first item is an alias name and whose + second item is the name of the component or sub-component it is to + refer to.

+

If this method is called during megawidget construction, any + component options supplied to the megawidget constructor which + refer to this component (by componentName or componentGroup) + are added to the kw dictionary before calling widgetClass. If + the dictionary contains a 'pyclass' key, then this item is + removed from the dictionary and the value is used instead of + widgetClass. For more details see The pyclass component option + section.

+ +

This method may be called by derived classes during or after + megawidget construction. It returns the instance of the class + created.

+ + + +
+ +
createlabel(parent, childCols = 1, childRows = 1)
+Create a Tkinter.Label component named 'label' in the parent + widget. This is a convenience method used by several megawidgets + that require an optional label. The widget must have options + named labelpos and labelmargin. If labelpos is None, no + label is created. Otherwise, a label is created and positioned + according to the value of labelpos and labelmargin. The label + is added to the parent using the grid() method, with childCols + and childRows indicating how many rows and columns the label + should span. Note that all other child widgets of the parent + must be added to the parent using the grid() method. The + createlabel() method may be called by derived classes during + megawidget construction.

+ + +
+ +
defineoptions(keywords, optionDefs, dynamicGroups = ())
+Create options for this megawidget. The optionDefs argument + defines the options. It is a sequence of 3-element tuples, + (name, default, callback), where name is the name of the + option, default is its default value and callback is the + function to call when the value of the option is set by a call to + configure(). The keywords argument should be the keyword + arguments passed in to the constructor of the megawidget. The user + may override the default value of an option by supplying a keyword + argument to the constructor.

+

If any option created by a base class is also defined by + optionDefs, then the derived class's default value will take + precedence over the base class's. If the callback field is not + None, then this will also override the callback set by the base + class.

+ +

If callback is Pmw.INITOPT, then the option is an + initialisation option.

+ +

The dynamicGroups argument contains a list of the groups of the + components created dynamically by this megawidget. If a group is + included in this list, then it not an error if a keyword argument + for the group is given to the constructor or to configure(), + even when no components with this group have been created.

+ +

If defineoptions() is called, it must be called once in the + megawidget constructor before the call to the constructor of the + base class and there must be a matching call to + initialiseoptions() at the end of the constructor.

+ + + +
+ +
destroy()
+Destroy the hull component widget, if it exists, including all + of its children.

+ + +
+ +
destroycomponent(name)
+Remove the megawidget component called name. This method may be + called by derived classes to destroy a megawidget component. It + destroys the component widget and then removes all record of the + component from the megawidget.

+ + +
+ +
hulldestroyed()
+Return true if the Tk widget corresponding to the hull component + has been destroyed.

+ + +
+ +
initialiseoptions(dummy = None)
+Check keyword arguments and call option callback functions. This + method must be called, at the end of a megawidget constructor, if + and only if defineoptions() was also called in the constructor. + The dummy argument is not required, but is retained for + backwards compatibility.

+

It checks that all keyword arguments given to the constructor have + been used. If not, it raises an error indicating which arguments + were unused. A keyword is defined to be used if, during the + construction of a megawidget, it is defined in a call to + defineoptions() or addoptions() (by the megawidget or one of + its base classes), or it references, by name, a component of the + megawidget, or it references, by group, at least one component. + It also calls the configuration callback function for all options + that have a callback.

+ +

This method is only effective when called by the constructor of + the leaf class, that is, the class in the class hierarchy which + first called defineoptions(). For all other classes in the + class hierarchy (base classes), the method returns immediately.

+ + + +
+ +
interior()
+Return the widget framing the interior space in which any children + of this megawidget should be created. By default, this returns + the hull component widget, if one was created, or None + otherwise. A subclass should use the widget returned by + interior() as the parent of any components or sub-widgets it + creates. Megawidgets which can be further subclassed, such as + Pmw.Dialog, should redefine this method to return the widget in + which subclasses should create children. The overall containing + widget is always available as the hull component.

+ + +
+ +
isinitoption(option)
+If option is an initialisation option, return true. Otherwise, + return false (the option is a configuration option). The option + argument must be an option of this megawidget, not an option of a + component. Otherwise an exception is raised.

+ + +
+ +
options()
+Return a sorted list of this megawidget's options. Each item in + the list is a 3-element tuple, (option, default, isinit), + where option is the name of the option, default is its default + value and isinit is true if the option is an initialisation + option.

+ + +
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 22 May 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/MegaToplevel.html b/Pmw/Pmw_1_2/doc/MegaToplevel.html new file mode 100644 index 00000000..53c1fe03 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/MegaToplevel.html @@ -0,0 +1,267 @@ + + + + + + Pmw.MegaToplevel reference manual + + + + +

Pmw.MegaToplevel

+ +
+

Name

+

Pmw.MegaToplevel() - + base class for megawidgets within a toplevel +

+ + +
+

Inherits

+Pmw.MegaArchetype
+
+

Description

+

+ This class creates a megawidget contained within a toplevel + window. It may be used directly to create a toplevel megawidget + or it may be used as a base class for more specialised toplevel + megawidgets, such as Pmw.Dialog. It creates a Tkinter.Toplevel + component, named hull, to act as the container of the megawidget. + The window class name for the hull widget is set to the + most-specific class name for the megawidget. Derived classes + specialise this class by creating other widget components as + children of the hull widget.

+ +

The megawidget may be used as either a normal toplevel window or + as a modal dialog. Use show() and withdraw() for normal use + and activate() and deactivate() for modal dialog use. If the + window is deleted by the window manager while being shown + normally, the default behaviour is to destroy the window. If the + window is deleted by the window manager while the window is active + (ie: when used as a modal dialog), the window is deactivated. + Use the userdeletefunc() and usermodaldeletefunc() methods to + override these behaviours. Do not call protocol() to set the + WM_DELETE_WINDOW window manager protocol directly if you want to + use this window as a modal dialog.

+ +

The currently active windows form a stack with the most recently + activated window at the top of the stack. All mouse and + keyboard events are sent to this top window. When it + deactivates, the next window in the stack will start to receive + events.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is None.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaArchetype. +In addition, methods from the +Tkinter.Toplevel class +are forwarded by this megawidget to the +hull component. +

+ +
activate(globalMode = 0, geometry = 'centerscreenfirst')
+Display the window as a modal dialog. This means that all mouse + and keyboard events go to this window and no other windows can + receive any events. If you do not want to restrict mouse and + keyboard events to this window, use the show() method instead.

+

If the BLT extension to Tk is present, a busy cursor will be + displayed on other toplevel windows, using Pmw.showbusycursor().

+ +

The activate() method does not return until the deactivate() + method is called, when the window is withdrawn, the grab released + and the result returned.

+ +

If globalMode is false, the window will grab control of the + pointer and keyboard, preventing any events from being delivered + to any other toplevel windows within the application. If + globalMode is true, the grab will prevent events from being + delivered to any other toplevel windows regardless of application. + Global grabs should be used sparingly, if at all.

+ +

If globalMode is 'nograb', then no grab is performed. If BLT + is present, this will allow mouse and keyboard events to be + received by other windows whose exclude busycursor attribute has + been set to true by a call to Pmw.setbusycursorattributes(). + Note that if 'nograb' is used and BLT is not present, then all + other windows will receive mouse and keyboard events. This is + because, in plain Tk, there is no way to specify that two windows + (only) receive events. If your application may be used without + BLT, then do not use 'nograb'.

+ +

When the window is displayed, it is positioned on the screen + according to geometry which may be one of:

+ +
centerscreenfirst
The window will be centered the first time it is activated. + On subsequent activations it will be positioned in the same + position as the last time it was displayed, even if it has + been moved by the user.

+ +
+
centerscreenalways
The window will be be centered on the screen (halfway across + and one third down).

+ +
+
first + spec
It is assumed that the rest of the argument (after 'first') + is a standard geometry specification. The window will be + positioned using this specification the first time it is + activated. On subsequent activations it will be positioned in + the same position as the last time it was displayed, even if + it has been moved by the user. For example, + geometry = first+100+100 will initially display the window + at position (100,100). Other calls to activate() will not + change the previous position of the window.

+ +
+
spec
This is a standard geometry specification. The window will be + be positioned using this specification.

+ +
+

If the BLT Tcl extension library is present, a clock cursor + will be displayed until the window is deactivated.

+ +

If the activatecommand option is callable, it is called just + before the window begins to wait for the result.

+ +

If the master option is not None, the window will become a + transient window of master, which should be a toplevel window. + If master has the special value of 'parent', the master is the + toplevel window of the window's parent.

+ + + +
+ +
active()
+Return true if the megawidget is currently active (that is, + activate() is currently waiting for a result to be passed to it + by a call to deactivate()).

+ + +
+ +
deactivate(result = None)
+This should be called while a call to activate() is waiting. It + will withdraw the window, release the grab and cause the + activate() call to return with the value of result.

+

If the deactivatecommand option is callable, it is called just + before the deactivate() method returns.

+ + + +
+ +
destroy()
+Destroy the hull component widget, including all of its + children. If the megawidget is currently active, deactivate it.

+ + +
+ +
show(master = None)
+Make the window visible. This raises or deiconifies the toplevel + window. If the window has previously been shown it will remain in + the same position. This means that calling withdraw() then + show() will not move the window, whereas calling withdraw() + then deiconify() may change the window's position. (This may + depend on the behaviour of the window manager.)

+ + +
+ +
userdeletefunc(func = None)
+If func is None, return the function that will be called + when the window is deleted by the window manager while being + displayed normally. If func is not None, set this function to + func. By default, the function is self.destroy.

+ + +
+ +
usermodaldeletefunc(func = None)
+If func is None, return the function that will be called + when the window is deleted by the window manager while it is + active (ie: when being used as a modal dialog). If func is not + None, set this function to func. By default, the function is + self.deactivate.

+ + +
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 22 May 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/MegaWidget.html b/Pmw/Pmw_1_2/doc/MegaWidget.html new file mode 100644 index 00000000..d18698bb --- /dev/null +++ b/Pmw/Pmw_1_2/doc/MegaWidget.html @@ -0,0 +1,83 @@ + + + + + + Pmw.MegaWidget reference manual + + + + +

Pmw.MegaWidget

+ +
+

Name

+

Pmw.MegaWidget() - + base class for megawidgets within a frame +

+ + +
+

Inherits

+Pmw.MegaArchetype
+
+

Description

+

+ This class creates a megawidget contained within a Tkinter.Frame + window. The class acts as the base class for megawidgets that are + not contained in their own toplevel window, such as Pmw.ButtonBox and + Pmw.ComboBox. It creates a Tkinter.Frame component, named hull, + to act as the container of the megawidget. The window class name + for the hull widget is set to the most-specific class name for + the megawidget. Derived classes specialise this class by + creating other widget components as children of the hull widget.

+ +

+ + +
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+
+ +

Methods

+This megawidget has no methods of its own. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaArchetype. +In addition, methods from the +Tkinter.Frame class +are forwarded by this megawidget to the +hull component. +

+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 22 May 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/MenuBar.gif b/Pmw/Pmw_1_2/doc/MenuBar.gif new file mode 100644 index 00000000..aa7a7bf8 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/MenuBar.gif differ diff --git a/Pmw/Pmw_1_2/doc/MenuBar.html b/Pmw/Pmw_1_2/doc/MenuBar.html new file mode 100644 index 00000000..e2c04a6c --- /dev/null +++ b/Pmw/Pmw_1_2/doc/MenuBar.html @@ -0,0 +1,399 @@ + + + + + + Pmw.MenuBar reference manual + + + + +

Pmw.MenuBar

+ +
+
+

Name

+

Pmw.MenuBar() - + manager megawidget for menu buttons and menus +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A menu bar is a container megawidget which manages a number of + menu buttons and dropdown menus. There + are methods to add menu buttons and menus to the menu bar and for + adding menu items to the menus. Menu buttons may be added to the + left or right of the megawidget. Each menu button and menu item may + have help text to be displayed by a Pmw.Balloon. Each menu + and cascaded menu (sub-menu) is referenced by name which is + supplied on creation.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
balloon +
+Specifies a Pmw.Balloon to display the help text for menu + buttons and menu items. If None, no help is displayed. If the + balloon has an associated Pmw.MessageBar, the help text will also be + displayed there. The default is None.

+ + +
+ +
hotkeys +
+Initialisation option. If true, keyboard accelerators will be assigned to each menu + button and menu item. Keyboard accelerators can be used to access + the menus without using the mouse. The accelerator character is + always one of the alphanumeric characters in the text label of the + menu or menu item and is indicated by an underline.

+

To select a menu, simultaneously press the <Alt> key and the + accelerator character indicated on a menu button. The arrows keys + can then be used to select other menus and menu items. To invoke a + menu item, press <Return> or press the accelerator character + indicated on the menu item.

+ +

Each accelerator character will be assigned automatically unless + traverseSpec is supplied to the addmenu(), addmenuitem() or + addcascademenu() methods. The automatically selected + accelerator character for a menu button (or menu item) is the + first character in the label text that has not already been used + as an accelerator for a menu button (or in the menu containing the + menu item).

+ +

If traverseSpec is given, it must be either an integer or a + character. If an integer, it specifies the index of the character + in the label text to use as the accelerator character. If a + character, it specifies the character to use as the accelerator + character. The default is 1.

+ + + +
+ +
padx +
+Initialisation option. Specifies a padding distance to leave between each menu button in + the x direction and also between the menu buttons and the outer + edge of the menu bar. The default is 0.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+
+

Dynamic components

+

+ Menu button components are created dynamically by the + addmenu() method. By default, these are of type + Tkinter.Menubutton and are created with a component group of + Button.

+ +

Menu components are created dynamically by the addmenu() and + addcascademenu() methods. By default, these are of type + Tkinter.Menu and are created with a component group of Menu.

+

+ + + +
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
addcascademenu(parentMenuName, menuName, statusHelp = '', traverseSpec = None, **kw)
+Add a cascade menu (sub-menu) to the menu parentMenuName. The + menuName argument must not be the same as any menu already + created using the addmenu() or addcascademenu() methods.

+

A menu item in the parent menu is created (with the + add_cascade() method of the parent menu) using all keyword + arguments except tearoff.

+ +

If the label keyword argument is not given, the label option + of the menu item defaults to menuName. If the underline + keyword argument is not given (and the hotkeys megawidget option + is true) the underline option is determined as described under + hotkeys and is used to specify the keyboard accelerator.

+ +

The statusHelp argument is used as the help string for the menu + item. This is displayed using the showstatus() method of the + balloon.

+ +

The tearoff keyword argument, if present, is passed to the + constructor of the menu. The menu is created as a component named + menuName-menu.

+ + + +
+ +
addmenu(menuName, balloonHelp, statusHelp = None, side = 'left', traverseSpec = None, **kw)
+Add a menu button and its associated menu to the menu bar. The + menuName argument must not be the same as any menu already + created using the addmenu() or addcascademenu() methods.

+

Any keyword arguments present (except tearoff) will be passed to + the constructor of the menu button. If the text keyword + argument is not given, the text option of the menu button + defaults to menuName. If the underline keyword argument is + not given (and the hotkeys megawidget option is true) the + underline option is determined as described under hotkeys and + is used to specify the keyboard accelerator. Each menu button is + packed into the menu bar using the given side, which should be + either left or right. The menu button is created as a + component named menuName-button.

+ +

If the balloon option has been defined, balloonHelp and + statusHelp are passed to the balloon as the help strings for the + menu button. See the bind() method of Pmw.Balloon for how these + strings may be displayed.

+ +

The tearoff keyword argument, if present, is passed to the + constructor of the menu. The menu is created as a component named + menuName-menu.

+ + + +
+ +
addmenuitem(menuName, itemType, statusHelp = '', traverseSpec = None, **kw)
+Add a menu item to the menu menuName. The kind of menu item is + given by itemType and may be one of command, separator, + checkbutton, radiobutton or cascade (although cascade menus + are better added using the addcascademenu() method). Any + keyword arguments present will be passed to the menu when creating + the menu item. See Tkinter.Menu for the valid options for each + item type. In addition, a keyboard accelerator may be + automatically given to the item, as described under hotkeys.

+

When the mouse is moved over the menu item, the helpString will + be displayed by the balloon's statuscommand.

+ + + +
+ +
deletemenu(menuName)
+Delete the menu menuName and all its items. The menu may either + be a toplevel menu (in which case the corresponding menu button is + also deleted) or a cascade menu.

+ + +
+ +
deletemenuitems(menuName, start, end = None)
+Delete menu items from the menu menuName. If end is not + given, the start item is deleted. Otherwise all items from + start to end are deleted.

+ + +
+ +
disableall()
+Disable all toplevel menus.

+ + +
+ +
enableall()
+Enable all toplevel menus.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the Balloon.
+        self.balloon = Pmw.Balloon(parent)
+
+        # Create and pack the MenuBar.
+        menuBar = Pmw.MenuBar(parent,
+                hull_relief = 'raised',
+                hull_borderwidth = 1,
+                balloon = self.balloon)
+        menuBar.pack(fill = 'x')
+        self.menuBar = menuBar
+
+        # Add some buttons to the MenuBar.
+        menuBar.addmenu('File', 'Close this window or exit')
+        menuBar.addmenuitem('File', 'command', 'Close this window',
+                command = PrintOne('Action: close'),
+                label = 'Close')
+        menuBar.addmenuitem('File', 'separator')
+        menuBar.addmenuitem('File', 'command', 'Exit the application',
+                command = PrintOne('Action: exit'),
+                label = 'Exit')
+
+        menuBar.addmenu('Edit', 'Cut, copy or paste')
+        menuBar.addmenuitem('Edit', 'command', 'Delete the current selection',
+                command = PrintOne('Action: delete'),
+                label = 'Delete')
+
+        menuBar.addmenu('Options', 'Set user preferences')
+        menuBar.addmenuitem('Options', 'command', 'Set general preferences',
+                command = PrintOne('Action: general options'),
+                label = 'General...')
+
+        # Create a checkbutton menu item.
+        self.toggleVar = Tkinter.IntVar()
+        # Initialise the checkbutton to 1:
+        self.toggleVar.set(1)
+        menuBar.addmenuitem('Options', 'checkbutton', 'Toggle me on/off',
+                label = 'Toggle',
+                command = self._toggleMe,
+                variable = self.toggleVar)
+        self._toggleMe()
+
+        menuBar.addcascademenu('Options', 'Size',
+                'Set some other preferences', traverseSpec = 'z', tearoff = 1)
+        for size in ('tiny', 'small', 'average', 'big', 'huge'):
+            menuBar.addmenuitem('Size', 'command', 'Set size to ' + size,
+                    command = PrintOne('Action: size ' + size),
+                    label = size)
+
+        menuBar.addmenu('Help', 'User manuals', side = 'right')
+        menuBar.addmenuitem('Help', 'command', 'About this application',
+                command = PrintOne('Action: about'),
+                label = 'About...')
+
+        # Create and pack the main part of the window.
+        self.mainPart = Tkinter.Label(parent,
+                text = 'This is the\nmain part of\nthe window',
+                background = 'black',
+                foreground = 'white',
+                padx = 30,
+                pady = 30)
+        self.mainPart.pack(fill = 'both', expand = 1)
+
+        # Create and pack the MessageBar.
+        self.messageBar = Pmw.MessageBar(parent,
+                entry_width = 40,
+                entry_relief='groove',
+                labelpos = 'w',
+                label_text = 'Status:')
+        self.messageBar.pack(fill = 'x', padx = 10, pady = 10)
+        self.messageBar.message('state', 'OK')
+
+        buttonBox = Pmw.ButtonBox(parent)
+        buttonBox.pack(fill = 'x')
+        buttonBox.add('Disable\nall', command = menuBar.disableall)
+        buttonBox.add('Enable\nall', command = menuBar.enableall)
+        buttonBox.add('Create\nmenu', command = self.add)
+        buttonBox.add('Delete\nmenu', command = self.delete)
+        buttonBox.add('Create\nitem', command = self.additem)
+        buttonBox.add('Delete\nitem', command = self.deleteitem)
+
+        # Configure the balloon to displays its status messages in the
+        # message bar.
+        self.balloon.configure(statuscommand = self.messageBar.helpmessage)
+
+        self.testMenuList = []
+
+    def _toggleMe(self):
+        print 'Toggle value:', self.toggleVar.get()
+
+    def add(self):
+        if len(self.testMenuList) == 0:
+            num = 0
+        else:
+            num = self.testMenuList[-1]
+        num = num + 1
+        name = 'Menu%d' % num
+        self.testMenuList.append(num)
+
+        self.menuBar.addmenu(name, 'This is ' + name)
+
+    def delete(self):
+        if len(self.testMenuList) == 0:
+            self.menuBar.bell()
+        else:
+            num = self.testMenuList[0]
+            name = 'Menu%d' % num
+            del self.testMenuList[0]
+            self.menuBar.deletemenu(name)
+
+    def additem(self):
+        if len(self.testMenuList) == 0:
+            self.menuBar.bell()
+        else:
+            num = self.testMenuList[-1]
+            menuName = 'Menu%d' % num
+            menu = self.menuBar.component(menuName + '-menu')
+            if menu.index('end') is None:
+                label = 'item X'
+            else:
+                label = menu.entrycget('end', 'label') + 'X'
+            self.menuBar.addmenuitem(menuName, 'command', 'Help for ' + label,
+                    command = PrintOne('Action: ' + menuName + ': ' + label),
+                    label = label)
+            
+    def deleteitem(self):
+        if len(self.testMenuList) == 0:
+            self.menuBar.bell()
+        else:
+            num = self.testMenuList[-1]
+            menuName = 'Menu%d' % num
+            menu = self.menuBar.component(menuName + '-menu')
+            if menu.index('end') is None:
+                self.menuBar.bell()
+            else:
+                self.menuBar.deletemenuitems(menuName, 0)
+            
+class PrintOne:
+    def __init__(self, text):
+        self.text = text
+
+    def __call__(self):
+        print self.text
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 22 April 2000 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/MessageBar.gif b/Pmw/Pmw_1_2/doc/MessageBar.gif new file mode 100644 index 00000000..0dc44465 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/MessageBar.gif differ diff --git a/Pmw/Pmw_1_2/doc/MessageBar.html b/Pmw/Pmw_1_2/doc/MessageBar.html new file mode 100644 index 00000000..69be04e7 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/MessageBar.html @@ -0,0 +1,302 @@ + + + + + + Pmw.MessageBar reference manual + + + + +

Pmw.MessageBar

+ +
+
+

Name

+

Pmw.MessageBar() - + information line for displaying short messages +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A message bar contains a single-line message display area. Messages + of several different types may displayed. Messages are cleared + after a period defined for each message type. Each message type + has a priority so that if the application attempts to display more + than one message at a time, the message with the highest priority + will be displayed. Messages may be accompanied by a number of + audible bells.

+ +

This megawidget can be used for both interactive help messages + (when the mouse enters certain widgets) and also for other general + messages.

+ +

To perform the help function it can cooperate with the Pmw.Balloon + megawidget so that the programmer (or user) can choose either + balloon help, message bar help, both or neither.

+ +

This megawidget supports a configurable number of message types. + The default types include 'state', 'help', 'usererror' and + 'systemerror'. The difference between these are the length of + time they are displayed, the number of bells that are rung and the + priority of the message. For example, the 'help' message type + is lower in priority than the 'usererror', so that error + messages will always be displayed in preference to help messages + regardless of the order the messages are created. The 'state' + message type is lowest in priority but has no timeout, so it + should contain messages describing the current state of the + application, such as Waiting for database connection or 'Waiting + for file to be unlocked'. Generally this should be set to the + empty string when the application is running normally. By default + the help messages (with message type 'help') time out after 5 + seconds, so that if the cursor happens to be left over a widget, + the application state will be redisplayed after a short time.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
messagetypes +
+Initialisation option. This defines what message types are supported by the message bar + and the characteristics of those message types. It is a + dictionary where the key is a string specifying a message type and + the value is a tuple of four integers, (priority, showtime, + bells, logmessage), where priority is the rank of the + message type, showtime is the number of seconds to display + messages of this message type, bells is the number of audible + bells to ring and logmessage is a boolean + specifying whether this message should be logged for retrieval + later. Messages with a higher priority are displayed in + preference to those with lower priority. If a high priority + message times out (because it has been displayed for showtime + seconds), then a lower priority message may be displayed. A + showtime of 0 means that the message will never time out and + is useful for displaying messages describing the current state of + the application as opposed to messages describing events. Logging + is not currently implemented. The default is

+
 {
+     'systemerror'  : (5, 10, 2, 1),
+     'usererror'    : (4, 5, 1, 0),
+     'busy'         : (3, 0, 0, 0),
+     'systemevent'  : (2, 5, 0, 0),
+     'userevent'    : (2, 5, 0, 0),
+     'help'         : (1, 5, 0, 0),
+     'state'        : (0, 0, 0, 0),
+ }
+ + + +
+ +
silent +
+If true, no audible bells will sound, regardless of the value for + bells defined in the messagetypes option. The default is 0.

+ + +
+ +
sticky +
+Initialisation option. The default is 'ew'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
entry +
+The widget where the messages are displayed. Long messages may be + scrolled horizontally by dragging with the middle mouse button. By default, this component is a Tkinter.Entry.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +In addition, methods from the +Tkinter.Entry class +are forwarded by this megawidget to the +entry component. +

+ +
helpmessage(text)
+A convenience method to display text in the message bar + according to the characteristics defined by the help message type. + Equivalent to message('help', text).

+ + +
+ +
message(type, text)
+Display text in the message bar according to the characteristics + defined by the type message type, as discussed under + messagetypes.

+ + +
+ +
resetmessages(type)
+Clear the type message and all message types with a lower + priority, except permanent messages, such as state. This is + useful to clear the busy message and any outstanding event and + help messages.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create and pack the MessageBar.
+        self._messagebar = Pmw.MessageBar(parent,
+                entry_width = 40,
+                entry_relief='groove',
+                labelpos = 'w',
+                label_text = 'Status:')
+        self._messagebar.pack(side = 'bottom', fill = 'x',
+                expand = 1, padx = 10, pady = 10)
+
+        # Create and pack the ScrolledListBox to change the MessageBar.
+        self.box = Pmw.ScrolledListBox(parent,
+                listbox_selectmode='single',
+                items=('state', 'help', 'userevent', 'systemevent',
+                        'usererror', 'systemerror', 'busy',),
+                label_text='Message type',
+                labelpos='n',
+                selectioncommand=self.selectionCommand)
+        self.box.pack(fill = 'both', expand = 'yes', padx = 10, pady = 10)
+
+        self._index = 0
+        self._stateCounter = 0
+
+    def selectionCommand(self):
+        sels = self.box.getcurselection()
+        if len(sels) > 0:
+            self._index = self._index + 1
+            messagetype = sels[0]
+            if messagetype == 'state':
+                self._stateCounter = (self._stateCounter + 1) % 3
+                text = stateMessages[self._stateCounter]
+                if text != '':
+                    text = text + ' (' + messagetype + ')'
+                self._messagebar.message('state', text)
+            else:
+                text = messages[messagetype]
+                text = text + ' (' + messagetype + ')'
+                self._messagebar.message(messagetype, text)
+                if messagetype == 'busy':
+                    Pmw.showbusycursor()
+                    self.box.after(2000)
+                    Pmw.hidebusycursor()
+                    self._messagebar.resetmessages('busy')
+                    text = 'All files successfully removed'
+                    text = text + ' (userevent)'
+                    self._messagebar.message('userevent', text)
+
+
+messages = {
+    'help': 'Save current file',
+    'userevent': 'Saving file "foo"',
+    'busy': 'Busy deleting all files from file system ...',
+    'systemevent': 'File "foo" saved',
+    'usererror': 'Invalid file name "foo/bar"',
+    'systemerror': 'Failed to save file: file system full',
+}
+
+stateMessages = {
+    0: '',
+    1: 'Database is down',
+    2: 'Waiting for reply from database',
+}
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/MessageDialog.gif b/Pmw/Pmw_1_2/doc/MessageDialog.gif new file mode 100644 index 00000000..f6ac1643 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/MessageDialog.gif differ diff --git a/Pmw/Pmw_1_2/doc/MessageDialog.html b/Pmw/Pmw_1_2/doc/MessageDialog.html new file mode 100644 index 00000000..f3e35884 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/MessageDialog.html @@ -0,0 +1,326 @@ + + + + + + Pmw.MessageDialog reference manual + + + + +

Pmw.MessageDialog

+ +
+
+

Name

+

Pmw.MessageDialog() - + a dialog displaying a text message and an icon +

+ + +
+

Inherits

+Pmw.Dialog
+
+

Description

+

+ A message dialog is a dialog window which displays a simple + message to the user along with one or more buttons to press.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
borderx +
+Initialisation option. The padding to the left and right of the text message and icon. The default is 20.

+ + +
+ +
bordery +
+Initialisation option. The padding above and below the text message and icon. The default is 20.

+ + +
+ +
buttonboxpos +
+Initialisation option. Specifies on which side of the dialog window to place the button + box. Must be one of 'n', 's', 'e' or 'w'. The default is 's'.

+ + +
+ +
buttons +
+This must be a tuple or a list and specifies the names on the + buttons in the button box. The default is ('OK',).

+ + +
+ +
command +
+Specifies a function to call whenever a button in the button box + is invoked or the window is deleted by the window manager. The + function is called with a single argument, which is the name of + the button which was invoked, or None if the window was deleted + by the window manager.

+

If the value of command is not callable, the default behaviour + is to deactivate the window if it is active, or withdraw the + window if it is not active. If it is deactivated, deactivate() + is called with the button name or None as described above. The default is None.

+ + + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
defaultbutton +
+Specifies the default button in the button box. If the <Return> + key is hit when the dialog has focus, the default button will be + invoked. If defaultbutton is None, there will be no default + button and hitting the <Return> key will have no effect. The default is None.

+ + +
+ +
iconmargin +
+Initialisation option. The padding between the text message and icon. The default is 20.

+ + +
+ +
iconpos +
+Initialisation option. Specifies on which side of the text message to place the icon. + Must be one of 'n', 's', 'e' or 'w'. The default is None.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
separatorwidth +
+Initialisation option. If this is greater than 0, a separator line with the specified + width will be created between the button box and the child site, + as a component named separator. Since the default border of the + button box and child site is raised, this option does not + usually need to be set for there to be a visual separation between + the button box and child site. The default is 0.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
buttonbox +
+This is the button box containing the buttons for the dialog. By + default it is created with the options + (hull_borderwidth = 1, hull_relief = 'raised'). By default, this component is a Pmw.ButtonBox.

+ + +
+ +
dialogchildsite +
+This is the child site for the dialog, which may be used to + specialise the megawidget by creating other widgets within it. By + default it is created with the options + (borderwidth = 1, relief = 'raised'). By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
icon +
+If the iconpos option is not None, this component is created + to contain the icon label for the dialog. To display a bitmap as + an icon, set the icon_bitmap component option to any of the + forms acceptable to Tk, such as 'warning' or 'error'. By default, this component is a Tkinter.Label.

+ + +
+ +
message +
+The label to contain the text message for the dialog. To set + the text, use the message_text component option. By default, this component is a Tkinter.Label.

+ + +
+ +
separator +
+If the separatorwidth initialisation option is non-zero, the + separator component is the line dividing the area between the + button box and the child site. By default, this component is a Tkinter.Frame.

+ + +
+
+ +

Methods

+This megawidget has no methods of its own. +For a description of its inherited methods, see the +manual for its base class +Pmw.Dialog. +

+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        self.parent = parent
+
+        # Create dialog 1.
+        self.dialog1 = Pmw.MessageDialog(parent,
+            title = 'Simple message dialog',
+            defaultbutton = 0,
+            message_text = 'A simple message dialog\nwith no callback.')
+        self.dialog1.iconname('Simple message dialog')
+        self.dialog1.withdraw()
+
+        # Create dialog 2.
+        self.dialog2 = Pmw.MessageDialog(parent,
+            title = 'Bell ringing dialog',
+            message_text = 'This message dialog\nwill ring the bell ' +
+                'when\nyou click on the buttons.',
+            iconpos = 'w',
+            icon_bitmap = 'error',
+            command = self.execute2,
+            buttons = ('One', 'Two', 'Three', 'Close'))
+        self.dialog2.iconname('Bell ringing dialog')
+        self.dialog2.withdraw()
+
+        # Create dialog 3.
+        self.dialog3 = Pmw.MessageDialog(parent,
+            title = 'Vertical button dialog',
+            message_text = 'This message dialog\nhas the buttons on the\n' +
+                'right hand side.',
+            buttonboxpos = 'e',
+            iconpos = 'n',
+            icon_bitmap = 'warning',
+            buttons = ('Goodbye', 'Au revoir', 'Sayonara', 'Close'),
+            defaultbutton = 'Close')
+        self.dialog3.iconname('Vertical button dialog')
+        self.dialog3.withdraw()
+
+        # Create some buttons to launch the dialogs.
+        w = Tkinter.Button(parent, text = 'Simple dialog',
+                command = lambda self = self:
+                        self.dialog1.activate(geometry = 'first+100+100'))
+        w.pack(padx = 8, pady = 8)
+
+        w = Tkinter.Button(parent, text = 'Bell ringing dialog',
+                command = self.dialog2.activate)
+        w.pack(padx = 8, pady = 8)
+
+        w = Tkinter.Button(parent, text = 'Vertical buttons',
+                command = self.dialog3.activate)
+        w.pack(padx = 8, pady = 8)
+
+        w = Tkinter.Button(parent, text = 'On the fly dialog',
+                command = self._createOnTheFly)
+        w.pack(padx = 8, pady = 8)
+
+    def execute2(self, result):
+        print 'You clicked on', result
+        if result is None:
+            self.dialog2.deactivate(result)
+        elif result == 'Close':
+            self.dialog2.deactivate(result)
+        else:
+            for count in range({'One': 1, 'Two': 2, 'Three': 3}[result]):
+                if count != 0:
+                    self.dialog2.after(200)
+                self.dialog2.bell()
+
+    def _createOnTheFly(self):
+        dialog = Pmw.MessageDialog(self.parent,
+            title = 'On the fly dialog',
+            defaultbutton = 0,
+            buttons = ('OK', 'Apply', 'Cancel', 'Help'),
+            message_text = 'This dialog was created when you clicked ' +
+                'on the button.')
+        dialog.iconname('Simple message dialog')
+        result = dialog.activate()
+
+        print 'You selected', result
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/NoteBook.gif b/Pmw/Pmw_1_2/doc/NoteBook.gif new file mode 100644 index 00000000..206a88d3 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/NoteBook.gif differ diff --git a/Pmw/Pmw_1_2/doc/NoteBook.html b/Pmw/Pmw_1_2/doc/NoteBook.html new file mode 100644 index 00000000..38601f7e --- /dev/null +++ b/Pmw/Pmw_1_2/doc/NoteBook.html @@ -0,0 +1,344 @@ + + + + + + Pmw.NoteBook reference manual + + + + +

Pmw.NoteBook

+ +
+
+

Name

+

Pmw.NoteBook() - + a set of tabbed pages +

+ + +
+

Inherits

+Pmw.MegaArchetype
+
+

Description

+

+ A notebook contains a set of tabbed pages. At any one time only + one of these pages (the selected page) is visible, with the + other pages being hidden "beneath" it. Another page in the + notebook may be displayed by clicking on the tab attached to the + page. The tabs are displayed along the top edge.

+ +

Optionally, the notebook may be displayed without tabs. In this + case, another selection widget, such as Pmw.OptionMenu, may be used + to select the pages.

+ +

This megawidget is derived from Pmw.MegaArchetype (not Pmw.MegaWidget + like most other megawidgets), with the hull class being + Tkinter.Canvas.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
arrownavigation +
+Initialisation option. If true and a tab button has the keyboard focus, then the Left and + Right arrow keys can be used to select the page before or after + the tab button with the focus. The default is 1.

+ + +
+ +
borderwidth +
+Initialisation option. The width of the border drawn around each tab and around the + selected page. The default is 2.

+ + +
+ +
createcommand +
+Specifies a function to call when a page is selected for the first + time. The function is called with a single argument, which is the + name of the selected page, and is called before the raisecommand + function. This allows the creation of the page contents to be + deferred until the page is first displayed. The default is None.

+ + +
+ +
lowercommand +
+Specifies a function to call when the selected page is replaced + with a new selected page. The function is called with a single + argument, which is the name of the previously selected page, and + is called before the createcommand or raisecommand functions. The default is None.

+ + +
+ +
pagemargin +
+Initialisation option. The margin (in pixels) around the selected page inside the + notebook's page border. The default is 4.

+ + +
+ +
raisecommand +
+Specifies a function to call when a new page is selected. The + function is called with a single argument, which is the name of + the selected page. The default is None.

+ + +
+ +
tabpos +
+Initialisation option. Specifies the location of the tabs. If 'n', tabs are created + for each page and positioned at the top of the notebook. If + None, no tabs are created, in which case another selection + widget can be used to select pages by calling the selectpage() + method. The default is 'n'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+This acts as the body for the megawidget. The contents of the + megawidget are created as canvas items and positioned in the + hull using the canvas coordinate system. By default, this component is a Tkinter.Canvas.

+ + +
+
+

Dynamic components

+

+ Page and tab components are created dynamically by the add() + and insert() methods. By default, the pages are of type + Tkinter.Frame and are created with a component group of Page + and the tabs are of type Tkinter.Button and are created with a + component group of Tab.

+

+ + + +
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaArchetype. +In addition, methods from the +Tkinter.Canvas class +are forwarded by this megawidget to the +hull component. +

+ +
add(pageName, **kw)
+Add a page at the end of the notebook. See the insert() method + for full details.

+ + +
+ +
delete(*pageNames)
+Delete the pages given by pageNames from the notebook. Each of + the pageNames may have any of the forms accepted by the + index() method.

+

If the currently selected page is deleted, then the next page, in + index order, is selected. If the end page is deleted, then the + previous page is selected.

+ + + +
+ +
getcurselection()
+Return the name of the currently selected page.

+ + +
+ +
index(index, forInsert = 0)
+Return the numerical index of the page corresponding to index. + This may be specified in any of the following forms:

+
name
Specifies the page labelled name.

+ +
+
number
Specifies the page numerically, where 0 corresponds to + the first page.

+ +
+
Pmw.END
Specifies the last page.

+ +
+
Pmw.SELECT
Specifies the currently selected page.

+ +
+

If forInsert is true, Pmw.END returns the number of pages + rather than the index of the last page.

+ + + +
+ +
insert(pageName, before = 0, **kw)
+Add a page to the notebook as a component named pageName. The + page is added just before the page specified by before, which + may have any of the forms accepted by the index() method. If + tabpos is not None, also create a tab as a component named + pageName-tab. Keyword arguments prefixed with page_ or + tab_ are passed to the respective constructors when creating the + page or tab. If the tab_text keyword argument is not given, the + text option of the tab defaults to pageName. If a page is + inserted into an empty notebook, the page is selected. To add a + page to the end of the notebook, use add(). The method returns + the pageName component widget.

+ + +
+ +
nextpage(pageIndex = None)
+If pageIndex is None, then select the page after the + currently selected page. Otherwise select the page after + pageIndex, which may have any of the forms accepted by the + index() method.

+ + +
+ +
page(pageIndex)
+Return the frame component widget of the page pageIndex, where + pageIndex may have any of the forms accepted by the index() + method.

+ + +
+ +
pagenames()
+Return a list of the names of the pages, in display order.

+ + +
+ +
previouspage(pageIndex = None)
+If pageIndex is None, then select the page before the + currently selected page. Otherwise select the page before + pageIndex, which may have any of the forms accepted by the + index() method.

+ + +
+ +
recolorborders()
+Change the color of the page and tab borders. This method is + required because the borders are created as canvas polygons and + hence do not respond to normal color changing techniques, such as + Pmw.Color.changecolor().

+ + +
+ +
selectpage(page)
+Select page to be the currently selected page. The page will be + raised and the previous selected page will be lowered.

+ + +
+ +
setnaturalsize(pageNames = None)
+Set the width and height of the notebook to be the maximum + requested width and height of the pages specified by pageNames. + If pageNames is None, the size of all pages are used to + determine the size of the notebook. Otherwise, pageNames must + be a list of page names whose sizes are to be used to determine + the size of the notebook. This method should be called after all + pages and their contents have been created. It calls + update_idletasks() so that the width and height of the pages can + be determined. This may cause the notebook to flash onto the + screen at the default size before resizing to the natural size.

+ + +
+ +
tab(pageIndex)
+Return the tab component widget of the page pageIndex, where + pageIndex may have any of the forms accepted by the index() + method. If tabpos is None, return None.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create and pack the NoteBook.
+        notebook = Pmw.NoteBook(parent)
+        notebook.pack(fill = 'both', expand = 1, padx = 10, pady = 10)
+
+        # Add the "Appearance" page to the notebook.
+        page = notebook.add('Appearance')
+        notebook.tab('Appearance').focus_set()
+
+        # Create the "Toolbar" contents of the page.
+        group = Pmw.Group(page, tag_text = 'Toolbar')
+        group.pack(fill = 'both', expand = 1, padx = 10, pady = 10)
+        b1 = Tkinter.Checkbutton(group.interior(), text = 'Show toolbar')
+        b1.grid(row = 0, column = 0)
+        b2 = Tkinter.Checkbutton(group.interior(), text = 'Toolbar tips')
+        b2.grid(row = 0, column = 1)
+
+        # Create the "Startup" contents of the page.
+        group = Pmw.Group(page, tag_text = 'Startup')
+        group.pack(fill = 'both', expand = 1, padx = 10, pady = 10)
+        home = Pmw.EntryField(group.interior(), labelpos = 'w',
+            label_text = 'Home page location:')
+        home.pack(fill = 'x', padx = 20, pady = 10)
+
+        # Add two more empty pages.
+        page = notebook.add('Helpers')
+        page = notebook.add('Images')
+
+        notebook.setnaturalsize()
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 30 October 1999 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/OptionMenu.gif b/Pmw/Pmw_1_2/doc/OptionMenu.gif new file mode 100644 index 00000000..a36b151e Binary files /dev/null and b/Pmw/Pmw_1_2/doc/OptionMenu.gif differ diff --git a/Pmw/Pmw_1_2/doc/OptionMenu.html b/Pmw/Pmw_1_2/doc/OptionMenu.html new file mode 100644 index 00000000..e1e0a6b6 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/OptionMenu.html @@ -0,0 +1,289 @@ + + + + + + Pmw.OptionMenu reference manual + + + + +

Pmw.OptionMenu

+ +
+
+

Name

+

Pmw.OptionMenu() - + single item selection megawidget +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ An option menu consists of a menu button + and an associated menu which pops up when the button is pressed. + The text displayed in the menu button is updated whenever an item + is selected in the menu. The currently selected value can be + retrieved from the megawidget.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
command +
+Specifies a function to call whenever a menu item is selected or + the invoke() method is called. The function is called with the + currently selected value as its single argument. The default is None.

+ + +
+ +
initialitem +
+Initialisation option. Specifies the initial selected value. This option is treated in + the same way as the index argument of the setitems() method. The default is None.

+ + +
+ +
items +
+Initialisation option. A sequence of strings containing the initial items to be displayed + in the menu component. The default is ().

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
sticky +
+Initialisation option. The default is 'ew'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
menu +
+The popup menu displayed when the menubutton is pressed. By default, this component is a Tkinter.Menu.

+ + +
+ +
menubutton +
+The menu button displaying the currently selected value. By default, this component is a Tkinter.Menubutton.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
getcurselection()
+Same as getvalue() method.

+ + +
+ +
getvalue()
+Return the currently selected value.

+ + +
+ +
index(index)
+Return the numerical index of the menu item corresponding to + index. This may be specified in any of the following forms:

+
name
Specifies the menu item labelled name.

+ +
+
number
Specifies the menu item numerically, where 0 corresponds to + the first menu item.

+ +
+
Pmw.END
Specifies the last menu item.

+ +
+
Pmw.SELECT
Specifies the currently selected menu item.

+ +
+ + +
+ +
invoke(index = Pmw.SELECT)
+Calling this method is the same as selecting the menu item + specified by index: the text displayed by the + menubutton component is updated and the function specified by + the command option is called. index may have any of the + forms accepted by the index() method. The value returned by + command is returned.

+ + +
+ +
setitems(items, index = None)
+Replace all the items in the menu component with those specified + by items, which must be a sequence of strings.

+

If index is not None, set the selected value to index, which + may have any of the forms accepted by the index() method.

+ +

If index is None and the textvariable option of the + menubutton component is the empty string, then if + the previous selected value is one of the items, then do not + change the selection. If the previous selected value is no longer + in items, then set the selected value to the first value in + items. If items is empty, set the selected value to the empty + string.

+ +

If index is None and the textvariable option of the + menubutton component is not the empty string, then do not set + the selected value. This assumes that the variable is already (or + will be) set to the desired value.

+ + + +
+ +
setvalue(text)
+Set the text displayed by the menubutton component to text.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create and pack the OptionMenu megawidgets.
+        # The first one has a textvariable.
+        self.var = Tkinter.StringVar()
+        self.var.set('steamed')
+        self.method_menu = Pmw.OptionMenu(parent,
+                labelpos = 'w',
+                label_text = 'Choose method:',
+                menubutton_textvariable = self.var,
+                items = ['baked', 'steamed', 'stir fried', 'boiled', 'raw'],
+                menubutton_width = 10,
+        )
+        self.method_menu.pack(anchor = 'w', padx = 10, pady = 10)
+
+        self.vege_menu = Pmw.OptionMenu (parent,
+                labelpos = 'w',
+                label_text = 'Choose vegetable:',
+                items = ('broccoli', 'peas', 'carrots', 'pumpkin'),
+                menubutton_width = 10,
+                command = self._printOrder,
+        )
+        self.vege_menu.pack(anchor = 'w', padx = 10, pady = 10)
+
+        self.direction_menu = Pmw.OptionMenu (parent,
+                labelpos = 'w',
+                label_text = 'Menu direction:',
+                items = ('flush', 'above', 'below', 'left', 'right'),
+                menubutton_width = 10,
+                command = self._changeDirection,
+        )
+        self.direction_menu.pack(anchor = 'w', padx = 10, pady = 10)
+
+        menus = (self.method_menu, self.vege_menu, self.direction_menu)
+        Pmw.alignlabels(menus)
+
+    def _printOrder(self, vege):
+        # Can use 'self.var.get()' instead of 'getcurselection()'.
+        print 'You have chosen %s %s.' % \
+            (self.method_menu.getcurselection(), vege)
+
+    def _changeDirection(self, direction):
+        for menu in (self.method_menu, self.vege_menu, self.direction_menu):
+            menu.configure(menubutton_direction = direction)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 23 October 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/PanedWidget.gif b/Pmw/Pmw_1_2/doc/PanedWidget.gif new file mode 100644 index 00000000..eecbbf20 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/PanedWidget.gif differ diff --git a/Pmw/Pmw_1_2/doc/PanedWidget.html b/Pmw/Pmw_1_2/doc/PanedWidget.html new file mode 100644 index 00000000..bcbb6630 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/PanedWidget.html @@ -0,0 +1,345 @@ + + + + + + Pmw.PanedWidget reference manual + + + + +

Pmw.PanedWidget

+ +
+
+

Name

+

Pmw.PanedWidget() - + frame subdivided into several resizable panes +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A paned widget is a container megawidget which manages a number of + resizable frames, known as panes. Each pane may act as the container for + other widgets. The user may interactively resize the panes by + dragging a small rectangle (the handle) or the line between the + panes (the separator). The panes may be arranged horizontally or + vertically. Each pane may have maximum and minimum limits of its + size.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
command +
+Specifies a function to be called whenever the size of any of the + panes changes. The function is called with a single argument, + being a list of the sizes of the panes, in order. For vertical + orientation, the size is the height of the panes. For + horizontal orientation, the size is the width of the panes. The default is None.

+ + +
+ +
handlesize +
+Initialisation option. Specifies the size in pixels of the square handle which appears on + the lines separating the panes. The default is 8.

+ + +
+ +
orient +
+Initialisation option. Specifies the orientation of the paned widget. This may be + 'horizontal' or 'vertical'. If 'vertical', the panes are + stacked above and below each other, otherwise the panes are laid + out side by side. The default is 'vertical'.

+ + +
+ +
separatorrelief +
+Initialisation option. Specifies the relief of the lines separating the panes. The default is 'sunken'.

+ + +
+ +
separatorthickness +
+Initialisation option. Specifies the thickness of the lines separating the panes. The default is 2.

+ + +
+
+

Pane options

+

+ Each pane has the following options. These may be set when + creating or configuring a pane. The value of each option may + be an integer, which specifies a pane size in pixels, or a + real number between 0.0 and 1.0, which specifies a pane size + proportional to the size of the entire paned widget.

+ +
size
Specifies the initial size of the pane. The default is 0.

+ +
+
min
Specifies the minimum size of the pane. The default is 0.

+ +
+
max
Specifies the maximum size of the pane. The default is a + very large number.

+

+ + +
+ +
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+
+

Dynamic components

+

+ Frame, separator and handle components are created dynamically + by the add() and insert() methods. The components are of type + Tkinter.Frame and are created with component groups of + Frame, Separator and Handle respectively.

+

+ + + +
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
add(name, **kw)
+Add a pane to the end of the paned widget as a component named + name. This is equivalent to calling insert() with before + set to the current number of panes. The method returns the name + component widget.

+ + +
+ +
configurepane(name, **kw)
+Configure the pane specified by name, where name is either an + integer, specifying the index of the pane, or a string, specifying + the name of the pane. The keyword arguments specify the new + values for the options for the pane. These options are described + in the Pane options section.

+ + +
+ +
delete(name)
+Delete the pane specified by name, where name is either an + integer, specifying the index of the pane, or a string, specifying + the name of the pane.

+

If the pane deleted was not the only pane in the paned widget, + also delete the separator and handle components named + separator-n and handle-n, where n is the number of + panes remaining.

+ + + +
+ +
insert(name, before = 0, **kw)
+Add a pane to the paned widget as a component named name. The + pane is added just before the pane specified by before, where + before may be either an integer, specifying the index of the + pane, or a string, specifying the name of the pane. The keyword + arguments specify the initial values for the options for the new + pane. These options are described in the Pane options section. + To add a pane to the end of the paned widget, use add().

+

The new pane is created as a Tkinter.Frame component named name. + If this is not the only pane, a separator and handle are also + created as components named separator-n and handle-n, + where n is one less than the number of panes. The method + returns the name component widget.

+ + + +
+ +
move(name, newPos, newPosOffset = 0)
+Move the pane specified by name to the new position specified by + newPos. The first two arguments may be either an integer, + specifying the index of the pane, or a string, specifying the name + of the pane. If newPosOffset is specified, it is added to the + newPos index. For example, to move a horizontal pane one pane + to the left, specify the name or index of the pane for both name + and newPos and specify -1 for newPosOffset.

+ + +
+ +
pane(name)
+Return the Tkinter.Frame pane widget for the pane specified by + name, where name is either an integer, specifying the index of + the pane, or a string, specifying the name of the pane.

+ + +
+ +
panes()
+Return a list of the names of the panes, in display order.

+ + +
+ +
setnaturalsize()
+If oriented horizontally, set the width of the paned widget to the + sum of the requested widths of all panes and set the height to the + maximum requested height of all panes.

+

If oriented vertically, set the height of the paned widget to the + sum of the requested heights of all panes and set the width to the + maximum requested width of all panes.

+ + + +
+ +
updatelayout()
+Recalculate size and position of panes. This method must be + called after adding or deleting one or more panes. However it + does not need to be called when panes are first added to a newly + created paned widget, before it has been displayed.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+
+        # Create a main PanedWidget with a few panes.
+        self.pw = Pmw.PanedWidget(parent,
+                orient='vertical',
+                hull_borderwidth = 1,
+                hull_relief = 'sunken',
+                hull_width=300,
+                hull_height=400)
+        for self.numPanes in range(4):
+            if self.numPanes == 1:
+                name = 'Fixed size'
+                pane = self.pw.add(name, min = .1, max = .1)
+            else:
+                name = 'Pane ' + str(self.numPanes)
+                pane = self.pw.add(name, min = .1, size = .25)
+            label = Tkinter.Label(pane, text = name)
+            label.pack(side = 'left', expand = 1)
+            button = Tkinter.Button(pane, text = 'Delete',
+                    command = lambda s=self, n=name: s.deletePane(n))
+            button.pack(side = 'left', expand = 1)
+            # TODO: add buttons to invoke self.moveOneUp and self.moveOneUp.
+
+        self.pw.pack(expand = 1, fill='both')
+
+        buttonBox = Pmw.ButtonBox(parent)
+        buttonBox.pack(fill = 'x')
+        buttonBox.add('Add pane', command = self.addPane)   
+        buttonBox.add('Move pane', command = self.move)   
+        self.moveSrc = 0
+        self.moveNewPos = 1
+        self.moveBack = 0
+
+    def move(self):
+        numPanes = len(self.pw.panes())
+        if numPanes == 0:
+            print 'No panes to move!'
+            return
+
+        if self.moveSrc >= numPanes:
+            self.moveSrc = numPanes - 1
+        if self.moveNewPos >= numPanes:
+            self.moveNewPos = numPanes - 1
+        print 'Moving pane', self.moveSrc, 'to new position', self.moveNewPos
+        self.pw.move(self.moveSrc, self.moveNewPos)
+
+        self.moveSrc, self.moveNewPos = self.moveNewPos, self.moveSrc
+        if self.moveBack:
+            if self.moveNewPos == numPanes - 1:
+                self.moveNewPos = 0
+                if self.moveSrc == numPanes - 1:
+                    self.moveSrc = 0
+                else:
+                    self.moveSrc = self.moveSrc + 1
+            else:
+                self.moveNewPos = self.moveNewPos + 1
+        self.moveBack = not self.moveBack
+
+    def addPane(self):
+        self.numPanes = self.numPanes + 1
+        name = 'Pane ' + str(self.numPanes)
+        print 'Adding', name
+        pane = self.pw.add(name, min = .1, size = .25)
+        label = Tkinter.Label(pane, text = name)
+        label.pack(side = 'left', expand = 1)
+        button = Tkinter.Button(pane, text = 'Delete',
+                command = lambda s=self, n=name: s.deletePane(n))
+        button.pack(side = 'left', expand = 1)
+        self.pw.updatelayout()
+
+    def deletePane(self, name):
+        print 'Deleting', name
+        self.pw.delete(name)
+        self.pw.updatelayout()
+
+    def moveOneUp(self, name):
+        self.pw.move(name, name, -1)
+
+    def moveOneDown(self, name):
+        self.pw.move(name, name, 1)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 14 April 2001 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/PmwFunctions.html b/Pmw/Pmw_1_2/doc/PmwFunctions.html new file mode 100644 index 00000000..af22de8f --- /dev/null +++ b/Pmw/Pmw_1_2/doc/PmwFunctions.html @@ -0,0 +1,766 @@ + + + + + + Pmw functions reference manual + + + + +

Pmw functions

+ +
+
Pmw.aboutcontact(value)
+

+ The value passed to this function is used to construct the text + displayed by Pmw.AboutDialog megawidgets created subsequently.

+ +

+ + +
+
Pmw.aboutcopyright(value)
+

+ The value passed to this function is used to construct the text + displayed by Pmw.AboutDialog megawidgets created subsequently.

+ +

+ + +
+
Pmw.aboutversion(value)
+

+ The value passed to this function is used to construct the text + displayed by Pmw.AboutDialog megawidgets created subsequently.

+ +

+ + +
+
Pmw.aligngrouptags(groups)
+

+ This function takes a sequence of Pmw.Groups and adjusts the + vertical position of the tags in each group so that they all have + the height of the tallest tag. This can be used when groups are + positioned side-by-side but the natural height of the tags are + different because, for example, different fonts with different + sizes are used.

+ +

+ + +
+
Pmw.alignlabels(widgets, sticky = None)
+

+ Adjust the size of the labels of all the widgets to be equal, so + that the body of each widget lines up vertically. This assumes + that each widget is a megawidget with a label component in + column 0 (ie, the labelpos option was set to 'w', 'wn' or + 'ws'). If sticky is set to a combination of 'n', 's', + 'e' and 'w', the label will be positioned within its cell + accordingly. For example to make labels right justified, set + sticky to 'e', 'ne' or 'se'.

+ +

+ + +
+
Pmw.alphabeticvalidator(text)
+

+ Validator function for Pmw.EntryField alphabetic standard validator.

+ +

+ + +
+
Pmw.alphanumericvalidator(text)
+

+ Validator function for Pmw.EntryField alphanumeric standard validator.

+ +

+ + +
+
Pmw.busycallback(command, updateFunction = None)
+

+ Create a wrapper function which displays a busy cursor while + executing command and return the wrapper. When the wrapper + function is called, it first calls Pmw.showbusycursor(), then + the command (passing any arguments to it), then Pmw.hidebusycursor(). + The return value of command is returned from the wrapper.

+ +

If updateFunction is specified, it is called just before the + call to Pmw.hidebusycursor(). This is intended to be the + Tkinter update() method, in which case it will clear any events + that may have occurred while command was executing. An example + of this usage is in the ShowBusy demonstration: run the + demonstration, click on the entry widget then click on the button + and type some characters while the busy cursor is displayed. No + characters should appear in the entry widget.

+ +

Note that the Tkinter update() method should only be called when + it is known that it can be safely called. One case where a + problem has been found is when a filehandler has been created (on + a non-blocking Oracle database connection), but the filehandler + does not read from the connection. The connection is read (by a + call to the Oracle fetch function ofen) in a loop which also + contains a call to _tkinter.dooneevent(). If update() is + called from dooneevent() and there is data to be read on the + connection, then the filehandler will be called continuously, thus + hanging the application.

+ +

+ + +
+
Pmw.clearbusycursor()
+

+ Unconditionally remove the event block and busy cursor from all + windows. This undoes all outstanding calls to + Pmw.showbusycursor().

+ +

+ + +
+
Pmw.datestringtojdn(text, format = 'ymd', separator = '/')
+

+ Return the Julian Day Number corresponding to the date in text. + A Julian Day Number is defined as the number of days since 1 Jan 4713 + BC. The date must be specified as three integers separated by the + separator character. The integers must be in the order specified by + format, which must be a combination of 'd', 'm' and 'y' in + any order. These give the order of the day, month and year + fields. Examples of valid input are:

+
 'dmy':  31/01/99  31/1/1999  31/1/99
+ 'mdy':  01/31/99  1/31/1999  1/31/99
+ 'ymd':  99/01/31  1999/1/31  99/1/31
+ + +

If the application's + pivot year (default 50) is not None and the year specified + in text has only one or two digits, then the year is + converted to a four digit year. If it is less than or equal to + the pivot year, then it is incremented by the application's + century value (default 2000). If it is more than the pivot year + then it is incremented by the century value less 100.

+ +

The function Pmw.setyearpivot() can be used to change the + default values for the application's + pivot and century.

+ +

+ + +
+
Pmw.datevalidator(text, format = 'ymd', separator = '/')
+

+ Validator function for Pmw.EntryField date standard validator.

+ +

+ + +
+
Pmw.displayerror(text)
+

+ This is a general purpose method for displaying background errors + to the user. The errors would normally be programming errors and + may be caused by errors in Tk callbacks or functions called by other + asynchronous events.

+ +

If the global error report file (set by calling + Pmw.reporterrorstofile()) is None, the error message `text` is + written to standard error and also shown in a text window. If + displayerror is called while previous error messages are being + displayed, the window is raised and the new error is queued. The + queued errors may be viewed by the user or ignored by dismissing + the window.

+ +

If the global error report file is not None, `text` is written + to the file. file may be any object with a write() method, + such as sys.stderr.

+ +

+ + +
+
Pmw.drawarrow(canvas, color, direction, tag, baseOffset = 0.25, edgeOffset = 0.15)
+

+ Draw a triangle in the Tkinter.Canvas canvas in the given + color. The value of direction may be 'up', 'down', + 'left' or 'right' and specifies which direction the arrow + should point. The values of baseOffset and edgeOffset specify + how far from the edges of the canvas the points of the triangles + are as a fraction of the size of the canvas.

+ +

+ + +
+
Pmw.forwardmethods(fromClass, toClass, toPart, exclude = ())
+

+ Forward methods from one class to another.

+ +

This function adds methods to the class fromClass. The names of + the methods added are the names of the methods of the class + toClass (and its base classes) except those which are already + defined by fromClass or are found in the exclude list. + Special methods with one or more leading or trailing underscores + are also excluded.

+ +

When one of the added methods is called, the method of the same + name is called on an instance defined by toPart and the return + value passed back. If toPart is a string, then it specifies the + name of an attribute (not a component) of the fromClass + object. The class of this attribute should be toClass. If + toPart is not a string, it must be a function taking a + fromClass object and returning a toClass object.

+ +

This function must be called outside of and after the definition + of fromClass.

+ +

For example:

+ +
class MyClass:
+    def __init__(self):
+        ...
+        self.__target = TargetClass()
+        ...
+
+    def foo(self):
+        pass
+
+    def findtarget(self):
+        return self.__target
+
+Pmw.forwardmethods(MyClass, TargetClass, '__target',
+    ['dangerous1', 'dangerous2'])
+
+# ...or...
+
+Pmw.forwardmethods(MyClass, TargetClass,
+    MyClass.findtarget, ['dangerous1', 'dangerous2'])
+ +

In both cases, all TargetClass methods will be forwarded from + MyClass except for dangerous1, dangerous2, special methods like + __str__, and pre-existing methods like foo.

+ +

+ + +
+
Pmw.grabstacktopwindow()
+

+ Return the window at the top of the grab stack (the window + currently with the grab) or None if the grab stack is empty (no + window has the grab). See also pushgrab().

+ +

+ + +
+
Pmw.hexadecimalvalidator(text)
+

+ Validator function for Pmw.EntryField hexadecimal standard validator.

+ +

+ + +
+
Pmw.hidebusycursor(forceFocusRestore = 0)
+

+ Undo one call to Pmw.showbusycursor(). If there are no + outstanding calls to Pmw.showbusycursor(), remove the event + block and busy cursor.

+ +

If the focus window has not been changed since the corresponding + call to Pmw.showbusycursor(), or if forceFocusRestore is true, + then the focus is restored to that saved by Pmw.showbusycursor().

+ +

+ + +
+
Pmw.initialise(root = None, size = None, fontScheme = None, useTkOptionDb = 0, noBltBusy = 0, disableKeyboardWhileBusy = None)
+

+ Initialise Pmw. This performs several functions:

+
  • Set up a trap in the Tkinter Toplevel constructor so that a + list of Toplevels can be maintained. A list of all Toplevel + windows needs to be kept so that Pmw.showbusycursor() can + create busy cursors for them.

    + +
  • +
  • Set up a trap in the Tkinter Toplevel and Frame destructors + so that Pmw is notified when these widgets are destroyed. + This allows Pmw to destroy megawidgets when their hull + widget is destroyed and to prune the list of Toplevels.

    + +
  • +
  • Modify Tkinter's CallWrapper class to improve the display of + errors which occur in callbacks. If an error occurs, the + new CallWrapper class calls Pmw.clearbusycursor() to + remove any outstanding busy cursors and calls + Pmw.displayerror() to display the error.

    + +
  • +
  • Using the window given by root, set the WM_DELETE_WINDOW + root window protocol to destroy the root window. This means + that the root window is destroyed if the window manager + deletes it. This is only done if the protocol has not been + set before the call to Pmw.initialise(). This protocol is + required if there is a modal dialog displayed and the window + manager deletes the root window. Otherwise the application + will not exit, even though there are no windows.

    + +
  • +
  • Set the base font size for the application to size. This + is used by Pmw.logicalfont() as the default point size for + fonts. If this is not given, the default is 14, except + under NT where it is 16. These are reasonable default + sizes for most screens, but for unusually high or low screen + resolutions, an appropriate size should be supplied. Note + that Tk's definition of point size, is somewhat + idiosyncratic.

    + +
  • +
  • Set the Tk option database for root according to + fontScheme. This changes the default fonts set by Tk. + fontScheme may be one of

    +
    None
    Do not change the Tk defaults.

    + +
    +
    'pmw1'
    If running under posix (Unix), set the default font to + be Helvetica with bold italic menus, italic scales and + a special balloon font 6 points smaller than the base + font size and with the 'pixel' field set to '12'. + For other operating systems (such as NT or Macintosh), + simply set the default font to be Helvetica. All + fonts are as returned by calls to Pmw.logicalfont().

    + +
    +
    'pmw2'
    This is the same as 'pmw1' except that under posix + the balloon font is 2 points smaller than the base + font size and the 'pixel' field is not set.

    + +
    +
    'default'
    This sets the default fonts using the Tk font naming + convention, rather than that returned by + Pmw.logicalfont(). The default font is bold + Helvetica. The font for entry widgets is Helvetica. + The font for text widgets is Courier The size of all + fonts is the application base font size as described + above.

    + +
    + +
  • +
  • If root is None, use the Tkinter default root window as the + root, if it has been created, or create a new Tk root window. + The initialise() method returns this root.

    + +
  • +
  • If useTkOptionDb is true, then, when a megawidget is + created, the Tk option database will be queried to get the + initial values of the options which have not been set in + the call to the constructor. The resource name used in the + query is the same as the option name and the resource class + is the option name with the first letter capitalised. If + useTkOptionDb is false, then options for newly created + megawidgets will be initialised to default values.

    + +
  • +
  • If noBltBusy is true, then Pmw.showbusycursor() will not + display a busy cursor, even if the BLT busy command is + present.

    + +
  • +
  • If disableKeyboardWhileBusy is false, then do not disable + keyboard input while displaying the busy cursor. Normally, + Pmw ignores keyboard input while displaying the busy cursor + by setting the focus for each toplevel window to the Blt + busy window. However, under NT, this may cause the toplevel + windows to be raised. If this is not acceptable, programs + running on NT can request show/hidebusycursor to not ignore + keyboard input by setting disableKeyboardWhileBusy to true + in Pmw.initialise().

    + +
+ +

It is not absolutely necessary to call this function to be able to use + Pmw. However, some functionality will be lost. Most importantly, + Pmw megawidgets will not be notified when their hull widget is + destroyed. This may prevent the megawidget from cleaning up + timers which will try to access the widget, hence causing a + background error to occur.

+ +

+ + +
+
Pmw.installedversions(alpha = 0)
+

+ If alpha is false, return the list of base versions of Pmw + that are currently installed and available for use. If alpha is + true, return the list of alpha versions.

+ +

+ + +
+
Pmw.integervalidator(text)
+

+ Validator function for Pmw.EntryField integer standard validator.

+ +

+ + +
+
Pmw.jdntoymd(jdn, julian = -1, papal = 1)
+

+ Return the year, month and day of the Julian Day Number jdn. If + julian is 1, then the date returned will be in the Julian + calendar. If julian is 0, then the date returned will be in + the modern calendar. If julian is -1, then which calendar to + use will be automatically determined by the value of jdn and + papal. If papal is true, then the date set by Pope Gregory + XIII's decree (4 October 1582) will be used as the last day to use + the Julian calendar. If papal is false, then the last day to + use the Julian calendar will be according to British-American + usage (2 September 1752).

+ +

+ + +
+
Pmw.logicalfont(name = 'Helvetica', sizeIncr = 0, **kw)
+

+ Return the full name of a Tk font, being a hyphen-separated list + of font properties. The logical name of the font is given by + name and may be one of 'Helvetica', 'Times', 'Fixed', + 'Courier' or 'Typewriter'. Pmw uses this name to define the + default values of many of the font properties. The size of the + font is the base font size for the application specified in the + call to Pmw.initialise() increased or decreased by the value of + sizeIncr. The other properties of the font may be specified by + other named arguments. These may be 'registry', 'foundry', + 'family', 'weight', 'slant', 'width', 'style', + 'pixel', 'size', 'xres', 'yres', 'spacing', + 'avgwidth', 'charset' and 'encoding'.

+ +

+ + +
+
Pmw.logicalfontnames()
+

+ Return the list of known logical font names that can be given + to Pmw.logicalfont().

+ +

+ + +
+
Pmw.numericvalidator(text)
+

+ Validator function for Pmw.EntryField numeric standard validator.

+ +

+ + +
+
Pmw.popgrab(window)
+

+ Remove window from the grab stack. If there are not more + windows in the grab stack, release the grab. Otherwise set the + grab and the focus to the next window in the grab stack. See also + pushgrab().

+ +

+ + +
+
Pmw.pushgrab(grabWindow, globalMode, deactivateFunction)
+

+ The grab functions (pushgrab(), popgrab(), releasegrabs() + and grabstacktopwindow()) are an interface to the Tk grab + command which implements simple pointer and keyboard grabs. When + a grab is set for a particular window, Tk restricts all pointer + events to the grab window and its descendants in Tk's window + hierarchy. The functions are used by the activate() and + deactivate() methods to implement modal dialogs.

+ +

Pmw maintains a stack of grabbed windows, where the window on the + top of the stack is the window currently with the grab. The grab + stack allows nested modal dialogs, where one modal dialog can be + activated while another modal dialog is activated. When the + second dialog is deactivated, the first dialog becomes active + again.

+ +

Use pushgrab() to add grabWindow to the grab stack. This + releases the grab by the window currently on top of the stack (if + there is one) and gives the grab and focus to the grabWindow. + If globalMode is true, perform a global grab, otherwise perform + a local grab. The value of deactivateFunction specifies a + function to call (usually grabWindow.deactivate) if popgrab() is + called (usually from a deactivate() method) on a window which is + not at the top of the stack (that is, does not have the grab or + focus). For example, if a modal dialog is deleted by the window + manager or deactivated by a timer. In this case, all dialogs + above and including this one are deactivated, starting at the top + of the stack.

+ +

For more information, see the Tk grab manual page.

+ +

+ + +
+
Pmw.realvalidator(text, separator = '.')
+

+ Validator function for Pmw.EntryField real standard validator.

+ +

+ + +
+
Pmw.releasegrabs()
+

+ Release grab and clear the grab stack. This should normally not + be used, use popgrab() instead. See also pushgrab().

+ +

+ + +
+
Pmw.reporterrorstofile(file = None)
+

+ Sets the global error report file, which is initially None. See + Pmw.displayerror()

+ +

+ + +
+
Pmw.setalphaversions(*alpha_versions)
+

+ Set the list of alpha versions of Pmw to use for this session to + the arguments. When searching for Pmw classes and functions, + these alpha versions will be searched, in the order given, before + the base version. This must be called before any other Pmw class + or function, except functions setting or querying versions.

+ +

+ + +
+
Pmw.setbusycursorattributes(window, **kw)
+

+ Use the keyword arguments to set attributes controlling the effect + on window (which must be a Tkinter.Toplevel) of future calls + to Pmw.showbusycursor(). The attributes are:

+ +
exclude
a boolean value which specifies whether the window + will be affected by calls to Pmw.showbusycursor(). If a window + is excluded, then the cursor will not be changed to a busy cursor + and events will still be delivered to the window. By default, + windows are affected by calls to Pmw.showbusycursor().

+ +
+
cursorName
the name of the cursor to use when displaying the + busy cursor. If None, then the default cursor is used.

+ +
+

+ + +
+
Pmw.setgeometryanddeiconify(window, geom)
+

+ Deiconify and raise the toplevel window and set its position and + size according to geom. This overcomes some problems with the + window flashing under X and correctly positions the window under + NT (caused by Tk bugs).

+ +

+ + +
+
Pmw.setversion(version)
+

+ Set the version of Pmw to use for this session to version. If + Pmw.setversion() is not called, the latest installed version of + Pmw will be used. This must be called before any other Pmw class + or function, except functions setting or querying versions.

+ +

+ + +
+
Pmw.setyearpivot(pivot, century = None)
+

+ Set the pivot year and century for the application's date + processing. These values are used in the datestringtojdn() + method, which is used by Pmw.Counter and Pmw.EntryField + and derived classes. The initial values of pivot and century + are 50 and 2000 repectively. Return a tuple containing the + old values of pivot and century.

+ +

+ + +
+
Pmw.showbusycursor()
+

+ Block events to and display a busy cursor over all windows in this + application that are in the state 'normal' or 'iconic', except + those windows whose exclude busycursor attribute has been set to + true by a call to Pmw.setbusycursorattributes().

+ +

If a window and its contents have just been created, + update_idletasks() may have to be called before + Pmw.showbusycursor() so that the window is mapped to the screen. + Windows created or deiconified after calling + Pmw.showbusycursor() will not be blocked.

+ +

To unblock events and remove the busy cursor, use + Pmw.hidebusycursor(). Nested calls to Pmw.showbusycursor() + may be made. In this case, a matching number of calls to + Pmw.hidebusycursor() must be made before the event block and + busy cursor are removed.

+ +

If the BLT extension to Tk is not present, this function has no + effect other than to save the value of the current focus window, + to be later restored by Pmw.hidebusycursor().

+ +

+ + +
+
Pmw.stringtoreal(text, separator = '.')
+

+ Return the real number represented by text. This is similar to + string.atof() except that the character representing the decimal + point in text is given by separator.

+ +

+ + +
+
Pmw.timestringtoseconds(text, separator = ':')
+

+ Return the number of seconds corresponding to the time in text. + The time must be specified as three integers separated by the + separator character and must be in the order hours, minutes and + seconds. The first number may be negative, indicating a negative + time.

+ +

+ + +
+
Pmw.timevalidator(text, separator = ':')
+

+ Validator function for Pmw.EntryField time standard validator.

+ +

+ + +
+
Pmw.tracetk(root = None, on = 1, withStackTrace = 0, file = None)
+

+ Print debugging trace of calls to, and callbacks from, the Tk + interpreter associated with the root window . If root is + None, use the Tkinter default root. If on is true, start + tracing, otherwise stop tracing. If withStackTrace is true, + print a python function call stacktrace after the trace for each + call to Tk. If file is None, print to standard error, + otherwise print to the file given by file.

+ +

For each call to Tk, the Tk command and its options are printed as + a python tuple, followed by the return value of the command (if + not the empty string). For example:

+ +
python executed:
+  button = Tkinter.Button()
+  button.configure(text = 'Hi')
+
+tracetk output:
+  CALL  TK> 1:  ('button', '.3662448') -> '.3662448'
+  CALL  TK> 1:  ('.3662448', 'configure', '-text', 'Hi')
+ +

Some calls from python to Tk (such as update, tkwait, + invoke, etc) result in the execution of callbacks from Tk to + python. These python callbacks can then recursively call into Tk. + When displayed by tracetk(), these recursive calls are indented + proportionally to the depth of recursion. The depth is also + printed as a leading number. The return value of a call to Tk + which generated recursive calls is printed on a separate line at + the end of the recursion. For example:

+ +
python executed:
+  def callback():
+      button.configure(text = 'Bye')
+      return 'Got me!'
+  button = Tkinter.Button()
+  button.configure(command = callback)
+  button.invoke()
+ +
tracetk output:
+  CALL  TK> 1:  ('button', '.3587144') -> '.3587144'
+  CALL  TK> 1:  ('.3587144', 'configure', '-command', '3638368callback')
+  CALL  TK> 1:  ('.3587144', 'invoke')
+  CALLBACK> 2:    callback()
+  CALL  TK> 2:    ('.3587144', 'configure', '-text', 'Bye')
+  CALL RTN> 1:  -> 'Got me!'
+ +

Pmw.initialise() must be called before tracetk() so that hooks + are put into the Tkinter CallWrapper class to trace callbacks from + Tk to python and also to handle recursive calls correctly.

+ +

+ + +
+
Pmw.version(alpha = 0)
+

+ If alpha is false, return the base version of Pmw being used + for this session. If Pmw.setversion() has not been called, this + will be the latest installed version of Pmw. If alpha is true, + return the list of alpha versions of Pmw being used for this + session, in search order. If Pmw.setalphaversions() has not + been called, this will be the empty list.

+ +

+ + +
+
Pmw.ymdtojdn(year, month, day, julian = -1, papal = 1)
+

+ Return the Julian Day Number corresponding to year, month and + day. See jdntoymd() for description of other arguments)

+ +

+ + +
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/PromptDialog.gif b/Pmw/Pmw_1_2/doc/PromptDialog.gif new file mode 100644 index 00000000..b82205c9 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/PromptDialog.gif differ diff --git a/Pmw/Pmw_1_2/doc/PromptDialog.html b/Pmw/Pmw_1_2/doc/PromptDialog.html new file mode 100644 index 00000000..f04b350b --- /dev/null +++ b/Pmw/Pmw_1_2/doc/PromptDialog.html @@ -0,0 +1,293 @@ + + + + + + Pmw.PromptDialog reference manual + + + + +

Pmw.PromptDialog

+ +
+
+

Name

+

Pmw.PromptDialog() - + selection dialog displaying an entry field +

+ + +
+

Inherits

+Pmw.Dialog
+
+

Description

+

+ The prompt dialog is a dialog window which displays an entry field + which can be used to prompt the user for a value.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
borderx +
+Initialisation option. The padding to the left and right of the entry field. The default is 20.

+ + +
+ +
bordery +
+Initialisation option. The padding above and below the entry field. The default is 20.

+ + +
+ +
buttonboxpos +
+Initialisation option. Specifies on which side of the dialog window to place the button + box. Must be one of 'n', 's', 'e' or 'w'. The default is 's'.

+ + +
+ +
buttons +
+This must be a tuple or a list and specifies the names on the + buttons in the button box. The default is ('OK',).

+ + +
+ +
command +
+Specifies a function to call whenever a button in the button box + is invoked or the window is deleted by the window manager. The + function is called with a single argument, which is the name of + the button which was invoked, or None if the window was deleted + by the window manager.

+

If the value of command is not callable, the default behaviour + is to deactivate the window if it is active, or withdraw the + window if it is not active. If it is deactivated, deactivate() + is called with the button name or None as described above. The default is None.

+ + + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
defaultbutton +
+Specifies the default button in the button box. If the <Return> + key is hit when the dialog has focus, the default button will be + invoked. If defaultbutton is None, there will be no default + button and hitting the <Return> key will have no effect. The default is None.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
separatorwidth +
+Initialisation option. If this is greater than 0, a separator line with the specified + width will be created between the button box and the child site, + as a component named separator. Since the default border of the + button box and child site is raised, this option does not + usually need to be set for there to be a visual separation between + the button box and child site. The default is 0.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
buttonbox +
+This is the button box containing the buttons for the dialog. By + default it is created with the options + (hull_borderwidth = 1, hull_relief = 'raised'). By default, this component is a Pmw.ButtonBox.

+ + +
+ +
dialogchildsite +
+This is the child site for the dialog, which may be used to + specialise the megawidget by creating other widgets within it. By + default it is created with the options + (borderwidth = 1, relief = 'raised'). By default, this component is a Tkinter.Frame.

+ + +
+ +
entryfield +
+The entry field for the user to enter a value. By default, this component is a Pmw.EntryField.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
separator +
+If the separatorwidth initialisation option is non-zero, the + separator component is the line dividing the area between the + button box and the child site. By default, this component is a Tkinter.Frame.

+ + +
+
+

Component aliases

+Sub-components of components of this megawidget +may be accessed via the following aliases.

+
entry +
+Alias for entryfield_entry. +
+
label +
+Alias for entryfield_label. +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.Dialog. +In addition, methods from the +Pmw.EntryField class +are forwarded by this megawidget to the +entryfield component. +

+ +
deleteentry(first, last = None)
+Delete text from the entry field's entry widget. An alias for + component('entry').delete().

+ + +
+ +
indexentry(index)
+An alias for component('entry').index().

+ + +
+ +
insertentry(index, text)
+Insert text into the entry field's entry widget. An alias for + component('entry').insert().

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the dialog to prompt for the password.
+        self.dialog = Pmw.PromptDialog(parent,
+            title = 'Password',
+            label_text = 'Password:',
+            entryfield_labelpos = 'n',
+            entry_show = '*',
+            defaultbutton = 0,
+            buttons = ('OK', 'Cancel'),
+            command = self.execute)
+        self.dialog.withdraw()
+
+        # Create the confirmation dialog.
+        self.confirm = Pmw.MessageDialog(
+            title = 'Are you sure?',
+            message_text = 'Are you really sure?',
+            defaultbutton = 0,
+            buttons = ('OK', 'Cancel'))
+        self.confirm.withdraw()
+
+        # Create button to launch the dialog.
+        w = Tkinter.Button(parent, text = 'Show prompt dialog',
+                command = self.dialog.activate)
+        w.pack(padx = 8, pady = 8)
+
+    def execute(self, result):
+        if result is None or result == 'Cancel':
+            print 'Password prompt cancelled'
+            self.dialog.deactivate(result)
+        else:
+            result = self.confirm.activate()
+            if result == 'OK':
+                print 'Password entered ' + self.dialog.get()
+                self.dialog.deactivate()
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/RadioSelect.gif b/Pmw/Pmw_1_2/doc/RadioSelect.gif new file mode 100644 index 00000000..026a1397 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/RadioSelect.gif differ diff --git a/Pmw/Pmw_1_2/doc/RadioSelect.html b/Pmw/Pmw_1_2/doc/RadioSelect.html new file mode 100644 index 00000000..bdf871c4 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/RadioSelect.html @@ -0,0 +1,405 @@ + + + + + + Pmw.RadioSelect reference manual + + + + +

Pmw.RadioSelect

+ +
+
+

Name

+

Pmw.RadioSelect() - + a set of buttons, some of which may be selected +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A radio select is a container megawidget which manages a number of + buttons. The buttons may be laid out either horizontally or + vertically. In single selection mode, only one button may be + selected at any one time. In multiple selection mode, several + buttons may be selected at the same time and clicking on a + selected button will deselect it.

+ +

The buttons displayed can be either standard buttons, radio + buttons or check buttons. When selected, standard buttons are + displayed sunken and radio and check buttons are displayed with + the appropriate indicator color and relief.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
buttontype +
+Initialisation option. Specifies the default type of buttons created by the add() + method. If 'button', the default type is Tkinter.Button. If + 'radiobutton', the default type is Tkinter.Radiobutton. If + 'checkbutton', the default type is Tkinter.Checkbutton.

+

If 'radiobutton', single selection mode is automatically set. + If 'checkbutton', multiple selection mode is automatically set. The default is 'button'.

+ + + +
+ +
command +
+Specifies a function to call when one of the buttons is clicked on + or when invoke() is called.

+

In single selection mode, the function is called with a single + argument, which is the name of the selected button.

+ +

In multiple selection mode, the function is called with the first + argument being the name of the button and the second argument + being true if the button is now selected or false if it is now + deselected. The default is None.

+ + + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
orient +
+Initialisation option. Specifies the direction in which the buttons are laid out. This + may be 'horizontal' or 'vertical'. The default is 'horizontal'.

+ + +
+ +
padx +
+Initialisation option. Specifies a padding distance to leave between each button in the x + direction and also between the buttons and the outer edge of the + radio select. The default is 5.

+ + +
+ +
pady +
+Initialisation option. Specifies a padding distance to leave between each button in the y + direction and also between the buttons and the outer edge of the + radio select. The default is 5.

+ + +
+ +
selectmode +
+Initialisation option. Specifies the selection mode: whether a single button or multiple + buttons can be selected at one time. If 'single', clicking on + an unselected button selects it and deselects all other buttons. + If 'multiple', clicking on an unselected button selects it and + clicking on a selected button deselects it. This option is + ignored if buttontype is 'radiobutton' or 'checkbutton'. The default is 'single'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
frame +
+If the label component has been created (that is, the labelpos + option is not None), the frame component is created to act as + the container of the buttons created by the add() method. If + there is no label component, then no frame component is + created and the hull component acts as the container. By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+
+

Dynamic components

+

+ Button components are created dynamically by the add() + method. The default type of the buttons depends on the value + of the buttontype option.

+ +

Button components are created with a component group of Button.

+

+ + + +
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
add(componentName, **kw)
+Add a button to the end of the radio select as a component + named componentName. with a default type as specified by + buttontype. Any keyword arguments present (except command) + will be passed to the constructor when creating the button. If + the text keyword argument is not given, the text option of the + button defaults to componentName. The method returns the + component widget.

+ + +
+ +
button(buttonIndex)
+Return the button specified by buttonIndex, which may have any + of the forms accepted by the index() method.

+ + +
+ +
deleteall()
+Delete all buttons and clear the current selection.

+ + +
+ +
getcurselection()
+Same as getvalue() method.

+ + +
+ +
getvalue()
+In single selection mode, return the name of the currently + selected button, or None if no buttons have been selected yet.

+

In multiple selection mode, return a list of the names of the + currently selected buttons.

+ + + +
+ +
index(index)
+Return the numerical index of the button corresponding to index. + This may be specified in any of the following forms:

+
name
Specifies the button named name.

+ +
+
number
Specifies the button numerically, where 0 corresponds to + the left (or top) button.

+ +
+
Pmw.END
Specifies the right (or bottom) button.

+ +
+ + +
+ +
invoke(index)
+Calling this method is the same as clicking on the button + specified by index: the buttons are displayed selected or + deselected according to the selection mode and command is + called. index may have any of the forms accepted by the + index() method. The value returned by command is returned.

+ + +
+ +
numbuttons()
+Return the number of buttons in the radio select.

+ + +
+ +
setvalue(textOrList)
+Set the current selection for the radio select to textOrList, + but do not invoke command.

+

In single selection mode, select only the button specified by the + string textOrList.

+ +

In multiple selection mode, select only the buttons specified by + the list textOrList.

+ + + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create and pack a horizontal RadioSelect widget.
+        horiz = Pmw.RadioSelect(parent,
+                labelpos = 'w',
+                command = self.callback,
+                label_text = 'Horizontal',
+                frame_borderwidth = 2,
+                frame_relief = 'ridge'
+        )
+        horiz.pack(fill = 'x', padx = 10, pady = 10)
+
+        # Add some buttons to the horizontal RadioSelect.
+        for text in ('Fruit', 'Vegetables', 'Cereals', 'Legumes'):
+            horiz.add(text)
+        horiz.invoke('Cereals')
+
+        # Create and pack a multiple selection RadioSelect widget.
+        self.multiple = Pmw.RadioSelect(parent,
+                labelpos = 'w',
+                command = self.multcallback,
+                label_text = 'Multiple\nselection',
+                frame_borderwidth = 2,
+                frame_relief = 'ridge',
+                selectmode = 'multiple',
+        )
+        self.multiple.pack(fill = 'x', padx = 10)
+
+        # Add some buttons to the multiple selection RadioSelect.
+        for text in ('Apricots', 'Eggplant', 'Rice', 'Lentils'):
+            self.multiple.add(text)
+        self.multiple.invoke('Rice')
+
+        # Create and pack a vertical RadioSelect widget, with checkbuttons.
+        self.checkbuttons = Pmw.RadioSelect(parent,
+                buttontype = 'checkbutton',
+                orient = 'vertical',
+                labelpos = 'w',
+                command = self.checkbuttoncallback,
+                label_text = 'Vertical,\nusing\ncheckbuttons',
+                hull_borderwidth = 2,
+                hull_relief = 'ridge',
+        )
+        self.checkbuttons.pack(side = 'left', expand = 1, padx = 10, pady = 10)
+
+        # Add some buttons to the checkbutton RadioSelect.
+        for text in ('Male', 'Female'):
+            self.checkbuttons.add(text)
+        self.checkbuttons.invoke('Male')
+        self.checkbuttons.invoke('Female')
+
+        # Create and pack a RadioSelect widget, with radiobuttons.
+        radiobuttons = Pmw.RadioSelect(parent,
+                buttontype = 'radiobutton',
+                orient = 'vertical',
+                labelpos = 'w',
+                command = self.callback,
+                label_text = 'Vertical,\nusing\nradiobuttons',
+                hull_borderwidth = 2,
+                hull_relief = 'ridge',
+        )
+        radiobuttons.pack(side = 'left', expand = 1, padx = 10, pady = 10)
+
+        # Add some buttons to the radiobutton RadioSelect.
+        for text in ('Male', 'Female', 'Both', 'Neither'):
+            radiobuttons.add(text)
+        radiobuttons.invoke('Both')
+
+    def callback(self, tag):
+        # This is called whenever the user clicks on a button
+        # in a single select RadioSelect widget.
+        print 'Button', tag, 'was pressed.'
+
+    def multcallback(self, tag, state):
+        # This is called whenever the user clicks on a button
+        # in the multiple select RadioSelect widget.
+        if state:
+           action = 'pressed.'
+        else:
+           action = 'released.'
+
+        print 'Button', tag, 'was', action, \
+                'Selection:', self.multiple.getcurselection()
+           
+    def checkbuttoncallback(self, tag, state):
+        # This is called whenever the user clicks on a button
+        # in the checkbutton RadioSelect widget.
+        if state:
+           action = 'pressed.'
+        else:
+           action = 'released.'
+
+        print 'Button', tag, 'was', action, \
+                'Selection:', self.checkbuttons.getcurselection()
+           
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 6 June 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ScrolledCanvas.gif b/Pmw/Pmw_1_2/doc/ScrolledCanvas.gif new file mode 100644 index 00000000..da7941ae Binary files /dev/null and b/Pmw/Pmw_1_2/doc/ScrolledCanvas.gif differ diff --git a/Pmw/Pmw_1_2/doc/ScrolledCanvas.html b/Pmw/Pmw_1_2/doc/ScrolledCanvas.html new file mode 100644 index 00000000..f3ebd216 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ScrolledCanvas.html @@ -0,0 +1,352 @@ + + + + + + Pmw.ScrolledCanvas reference manual + + + + +

Pmw.ScrolledCanvas

+ +
+
+

Name

+

Pmw.ScrolledCanvas() - + canvas with optional scrollbars +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A scrolled canvas consists of a standard canvas widget with optional + scrollbars which can be used to scroll the canvas. The scrollbars + can be dynamic, which means that a scrollbar will only be + displayed if it is necessary, that is, if the scrollregion of the + canvas is larger than the canvas.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
borderframe +
+Initialisation option. If true, the borderframe component will be created. The default is 0.

+ + +
+ +
canvasmargin +
+Initialisation option. The margin around the items in the canvas. Used by the + resizescrollregion() method. The default is 0.

+ + +
+ +
hscrollmode +
+The horizontal scroll mode. If 'none', the horizontal scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
scrollmargin +
+Initialisation option. The distance between the scrollbars and the enclosing canvas + widget. The default is 2.

+ + +
+ +
usehullsize +
+Initialisation option. If true, the size of the megawidget is determined solely by the + width and height options of the hull component.

+

Otherwise, the size of the megawidget is determined by the width + and height of the canvas component, along with the size and/or + existence of the other components, such as the label, the + scrollbars and the scrollmargin option. All these affect the + overall size of the megawidget. The default is 0.

+ + + +
+ +
vscrollmode +
+The vertical scroll mode. If 'none', the vertical scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
borderframe +
+A frame widget which snuggly fits around the canvas, to give the + appearance of a canvas border. It is created with a border so + that the canvas, which is created without a border, looks like it + has a border. By default, this component is a Tkinter.Frame.

+ + +
+ +
canvas +
+The canvas widget which is scrolled by the scrollbars. If the + borderframe option is true, this is created with a borderwidth + of 0 to overcome a known problem with canvas widgets: if a + widget inside a canvas extends across one of the edges of the + canvas, then the widget obscures the border of the canvas. + Therefore, if the canvas has no border, then this overlapping does + not occur. By default, this component is a Tkinter.Canvas.

+ + +
+ +
horizscrollbar +
+The horizontal scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
vertscrollbar +
+The vertical scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +In addition, methods from the +Tkinter.Canvas class +are forwarded by this megawidget to the +canvas component. +

+ +
bbox(*args)
+This method is explicitly forwarded to the canvas component's + bbox() method. Without this explicit forwarding, the bbox() + method (aliased to grid_bbox()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+ +
interior()
+Return the canvas widget within which the programmer should create + graphical items and child widgets. This is the same as + component('canvas').

+ + +
+ +
resizescrollregion()
+Resize the scrollregion of the canvas component to be the + bounding box covering all the items in the canvas plus a margin on + all sides, as specified by the canvasmargin option.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the ScrolledCanvas.
+        self.sc = Pmw.ScrolledCanvas(parent,
+                borderframe = 1,
+                labelpos = 'n',
+                label_text = 'ScrolledCanvas',
+                usehullsize = 1,
+                hull_width = 400,
+                hull_height = 300,
+        )
+
+        # Create a group widget to contain the scrollmode options.
+        w = Pmw.Group(parent, tag_text='Scroll mode')
+        w.pack(side = 'bottom', padx = 5, pady = 5)
+
+        hmode = Pmw.OptionMenu(w.interior(),
+                labelpos = 'w',
+                label_text = 'Horizontal:',
+                items = ['none', 'static', 'dynamic'],
+                command = self.sethscrollmode,
+                menubutton_width = 8,
+        )
+        hmode.pack(side = 'left', padx = 5, pady = 5)
+        hmode.invoke('dynamic')
+
+        vmode = Pmw.OptionMenu(w.interior(),
+                labelpos = 'w',
+                label_text = 'Vertical:',
+                items = ['none', 'static', 'dynamic'],
+                command = self.setvscrollmode,
+                menubutton_width = 8,
+        )
+        vmode.pack(side = 'left', padx = 5, pady = 5)
+        vmode.invoke('dynamic')
+
+        buttonBox = Pmw.ButtonBox(parent)
+        buttonBox.pack(side = 'bottom')
+        buttonBox.add('yview', text = 'Show\nyview', command = self.showYView)
+        buttonBox.add('scroll', text = 'Page\ndown', command = self.pageDown)
+        buttonBox.add('center', text = 'Center', command = self.centerPage)
+
+        # Pack this last so that the buttons do not get shrunk when
+        # the window is resized.
+        self.sc.pack(padx = 5, pady = 5, fill = 'both', expand = 1)
+
+        self.sc.component('canvas').bind('<1>', self.addcircle)
+
+        testEntry = Tkinter.Entry(parent)
+        self.sc.create_line(20, 20, 100, 100)
+        self.sc.create_oval(100, 100, 200, 200, fill = 'green')
+        self.sc.create_text(100, 20, anchor = 'nw',
+                text = 'Click in the canvas\nto draw ovals',
+                font = testEntry.cget('font'))
+        button = Tkinter.Button(self.sc.interior(),
+                text = 'Hello,\nWorld!\nThis\nis\na\nbutton.')
+        self.sc.create_window(200, 200,
+                anchor='nw',
+                window = button)
+
+        # Set the scroll region of the canvas to include all the items
+        # just created.
+        self.sc.resizescrollregion()
+
+        self.colours = ('red', 'green', 'blue', 'yellow', 'cyan', 'magenta',
+                'black', 'white')
+        self.oval_count = 0
+        self.rand = 12345
+
+    def sethscrollmode(self, tag):
+        self.sc.configure(hscrollmode = tag)
+
+    def setvscrollmode(self, tag):
+        self.sc.configure(vscrollmode = tag)
+
+    def addcircle(self, event):
+        x = self.sc.canvasx(event.x)
+        y = self.sc.canvasy(event.y)
+        width = 10 + self.random() % 100
+        height = 10 + self.random() % 100
+        self.sc.create_oval(
+            x - width, y - height, x + width, y + height,
+            fill = self.colours[self.oval_count])
+        self.oval_count = (self.oval_count + 1) % len(self.colours)
+        self.sc.resizescrollregion()
+
+    # Simple random number generator.
+    def random(self):
+        self.rand = (self.rand * 125) % 2796203
+        return self.rand
+
+    def showYView(self):
+        print self.sc.yview()
+
+    def pageDown(self):
+        self.sc.yview('scroll', 1, 'page')
+
+    def centerPage(self):
+        top, bottom = self.sc.yview()
+        size = bottom - top
+        middle = 0.5 - size / 2
+        self.sc.yview('moveto', middle)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 20 September 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ScrolledField.gif b/Pmw/Pmw_1_2/doc/ScrolledField.gif new file mode 100644 index 00000000..d1942e3d Binary files /dev/null and b/Pmw/Pmw_1_2/doc/ScrolledField.gif differ diff --git a/Pmw/Pmw_1_2/doc/ScrolledField.html b/Pmw/Pmw_1_2/doc/ScrolledField.html new file mode 100644 index 00000000..4c28cbc4 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ScrolledField.html @@ -0,0 +1,187 @@ + + + + + + Pmw.ScrolledField reference manual + + + + +

Pmw.ScrolledField

+ +
+
+

Name

+

Pmw.ScrolledField() - + single line scrollable output field +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A scrolled field displays a single line of text. If the text is + too wide to display in the megawidget it can be scrolled to the + left and right by the user by dragging with the middle mouse + button. The text is also selectable by clicking or dragging with + the left mouse button.

+ +

It can be used instead of a Tkinter.Label widget when displaying + text of unknown width such as application status messages.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
sticky +
+Initialisation option. The default is 'ew'.

+ + +
+ +
text +
+Specifies the text to display in the scrolled field. The default is ''.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
entry +
+This is used to display the text and allows the user to scroll and + select the text. The state of this component is set to + 'readonly' (or 'disabled' in earlier versions of Tcl/Tk which do + not support 'readonly'), so that the user is unable to modify the text. By default, this component is a Tkinter.Entry.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+
+ +

Methods

+This megawidget has no methods of its own. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +In addition, methods from the +Tkinter.Entry class +are forwarded by this megawidget to the +entry component. +

+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create and pack the ScrolledField.
+        self._field = Pmw.ScrolledField(parent, entry_width = 30,
+                entry_relief='groove', labelpos = 'n',
+                label_text = 'Scroll the field using the\nmiddle mouse button')
+        self._field.pack(fill = 'x', expand = 1, padx = 10, pady = 10)
+
+        # Create and pack a button to change the ScrolledField.
+        self._button = Tkinter.Button(parent, text = 'Change field',
+                command = self.execute)
+        self._button.pack(padx = 10, pady = 10)
+
+        self._index = 0
+        self.execute()
+
+    def execute(self):
+        self._field.configure(text = lines[self._index % len(lines)])
+        self._index = self._index + 1
+
+lines = (
+  'Alice was beginning to get very tired of sitting by her sister',
+  'on the bank, and of having nothing to do:  once or twice she had',
+  'peeped into the book her sister was reading, but it had no',
+  'pictures or conversations in it, "and what is the use of a book,"',
+  'thought Alice "without pictures or conversation?"',
+  'Alice\'s Adventures in Wonderland',
+  'Lewis Carroll',
+)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 23 August 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ScrolledFrame.gif b/Pmw/Pmw_1_2/doc/ScrolledFrame.gif new file mode 100644 index 00000000..089a201e Binary files /dev/null and b/Pmw/Pmw_1_2/doc/ScrolledFrame.gif differ diff --git a/Pmw/Pmw_1_2/doc/ScrolledFrame.html b/Pmw/Pmw_1_2/doc/ScrolledFrame.html new file mode 100644 index 00000000..5cfe3b3b --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ScrolledFrame.html @@ -0,0 +1,479 @@ + + + + + + Pmw.ScrolledFrame reference manual + + + + +

Pmw.ScrolledFrame

+ +
+
+

Name

+

Pmw.ScrolledFrame() - + frame with optional scrollbars +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A scrolled frame consists of a scrollable interior frame within a + clipping frame. The programmer can create other widgets within + the interior frame. If the frame becomes larger than the + surrounding clipping frame, the user can position the frame using + the horizontal and vertical scrollbars.

+ +

The scrollbars can be dynamic, which means that a scrollbar will + only be displayed if it is necessary. That is, if the frame is + smaller than the surrounding clipping frame, the scrollbar will be + hidden.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
borderframe +
+Initialisation option. If true, the borderframe component will be created. The default is 1.

+ + +
+ +
horizflex +
+Specifies how the width of the scrollable interior frame should be + resized relative to the clipping frame.

+

If 'fixed', the interior frame is set to the natural width, as + requested by the child widgets of the frame. If 'expand' and + the requested width of the interior frame is less than the width + of the clipping frame, the interior frame expands to fill the + clipping frame. If 'shrink' and the requested width of the + interior frame is more than the width of the clipping frame, the + interior frame shrinks to the width of the clipping frame. If + 'elastic', the width of the interior frame is always set to the + width of the clipping frame. The default is 'fixed'.

+ + + +
+ +
horizfraction +
+Initialisation option. The fraction of the width of the clipper frame to scroll the + interior frame when the user clicks on the horizontal scrollbar + arrows. The default is 0.05.

+ + +
+ +
hscrollmode +
+The horizontal scroll mode. If 'none', the horizontal scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
scrollmargin +
+Initialisation option. The distance between the scrollbars and the clipping frame. The default is 2.

+ + +
+ +
usehullsize +
+Initialisation option. If true, the size of the megawidget is determined solely by the + width and height options of the hull component.

+

Otherwise, the size of the megawidget is determined by the width + and height of the clipper component, along with the size and/or + existence of the other components, such as the label, the + scrollbars and the scrollmargin option. All these affect the + overall size of the megawidget. The default is 0.

+ + + +
+ +
vertflex +
+Specifies how the height of the scrollable interior frame should + be resized relative to the clipping frame.

+

If 'fixed', the interior frame is set to the natural height, + as requested by the child widgets of the frame. If 'expand' and + the requested height of the interior frame is less than the height + of the clipping frame, the interior frame expands to fill the + clipping frame. If 'shrink' and the requested height of the + interior frame is more than the height of the clipping frame, the + interior frame shrinks to the height of the clipping frame. If + 'elastic', the height of the interior frame is always set to the + height of the clipping frame. The default is 'fixed'.

+ + + +
+ +
vertfraction +
+Initialisation option. The fraction of the height of the clipper frame to scroll the + interior frame when the user clicks on the vertical scrollbar + arrows. The default is 0.05.

+ + +
+ +
vscrollmode +
+The vertical scroll mode. If 'none', the vertical scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
borderframe +
+A frame widget which snuggly fits around the clipper, to give the + appearance of a border. It is created with a border so that the + clipper, which is created without a border, looks like it has a + border. By default, this component is a Tkinter.Frame.

+ + +
+ +
clipper +
+The frame which is used to provide a clipped view of the frame + component. If the borderframe option is true, this is created + with a borderwidth of 0 to overcome a known problem with using + place to position widgets: if a widget (in this case the + frame component) is placed inside a frame (in this case the + clipper component) and it extends across one of the edges of the + frame, then the widget obscures the border of the frame. + Therefore, if the clipper has no border, then this overlapping + does not occur. By default, this component is a Tkinter.Frame.

+ + +
+ +
frame +
+The frame within the clipper to contain the widgets to be scrolled. By default, this component is a Tkinter.Frame.

+ + +
+ +
horizscrollbar +
+The horizontal scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
vertscrollbar +
+The vertical scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
interior()
+Return the frame within which the programmer may create widgets to + be scrolled. This is the same as component('frame').

+ + +
+ +
reposition()
+Update the position of the frame component in the clipper and + update the scrollbars.

+

Usually, this method does not need to be called explicitly, since + the position of the frame component and the scrollbars are + automatically updated whenever the size of the frame or + clipper components change or the user clicks in the scrollbars. + However, if horizflex or vertflex is 'expand', the + megawidget cannot detect when the requested size of the frame + increases to greater than the size of the clipper. Therefore, + this method should be called when a new widget is added to the + frame (or a widget is increased in size) after the initial + megawidget construction.

+ + + +
+ +
xview(mode = None, value = None, units = None)
+Query or change the horizontal position of the scrollable interior + frame. If mode is None, return a tuple of two numbers, each + between 0.0 and 1.0. The first is the position of the left edge + of the visible region of the contents of the scrolled frame, + expressed as a fraction of the total width of the contents. The + second is the position of the right edge of the visible region.

+

If mode == 'moveto', adjust the view of the interior so that + the fraction value of the total width of the contents is + off-screen to the left. The value must be between 0.0 and + 1.0.

+ +

If mode == 'scroll', adjust the view of the interior left or + right by a fixed amount. If what is 'units', move the view in + units of horizfraction. If what is pages, move the view in + units of the width of the scrolled frame. If value is positive, + move to the right, otherwise move to the left.

+ + + +
+ +
yview(mode = None, value = None, units = None)
+Query or change the vertical position of the scrollable interior + frame. If mode is None, return a tuple of two numbers, each + between 0.0 and 1.0. The first is the position of the top edge + of the visible region of the contents of the scrolled frame, + expressed as a fraction of the total height of the contents. The + second is the position of the bottom edge of the visible region.

+

If mode == 'moveto', adjust the view of the interior so that + the fraction value of the total height of the contents is + off-screen to the top. The value must be between 0.0 and + 1.0.

+ +

If mode == 'scroll', adjust the view of the interior up or + down by a fixed amount. If what is 'units', move the view in + units of vertfraction. If what is pages, move the view in + units of the height of the scrolled frame. If value is + positive, move to down, otherwise move up.

+ + + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the ScrolledFrame.
+        self.sf = Pmw.ScrolledFrame(parent,
+                labelpos = 'n', label_text = 'ScrolledFrame',
+                usehullsize = 1,
+                hull_width = 400,
+                hull_height = 220,
+        )
+
+        # Create a group widget to contain the flex options.
+        w = Pmw.Group(parent, tag_text='Flex')
+        w.pack(side = 'bottom', padx = 5, pady = 3)
+
+        hflex = Pmw.OptionMenu(w.interior(),
+                labelpos = 'w',
+                label_text = 'Horizontal:',
+                items = ['fixed', 'expand', 'shrink', 'elastic'],
+                command = self.sethflex,
+                menubutton_width = 8,
+        )
+        hflex.pack(side = 'left', padx = 5, pady = 3)
+        hflex.invoke('fixed')
+
+        vflex = Pmw.OptionMenu(w.interior(),
+                labelpos = 'w',
+                label_text = 'Vertical:',
+                items = ['fixed', 'expand', 'shrink', 'elastic'],
+                command = self.setvflex,
+                menubutton_width = 8,
+        )
+        vflex.pack(side = 'left', padx = 5, pady = 3)
+        vflex.invoke('fixed')
+
+        # Create a group widget to contain the scrollmode options.
+        w = Pmw.Group(parent, tag_text='Scroll mode')
+        w.pack(side = 'bottom', padx = 5, pady = 0)
+
+        hmode = Pmw.OptionMenu(w.interior(),
+                labelpos = 'w',
+                label_text = 'Horizontal:',
+                items = ['none', 'static', 'dynamic'],
+                command = self.sethscrollmode,
+                menubutton_width = 8,
+        )
+        hmode.pack(side = 'left', padx = 5, pady = 3)
+        hmode.invoke('dynamic')
+
+        vmode = Pmw.OptionMenu(w.interior(),
+                labelpos = 'w',
+                label_text = 'Vertical:',
+                items = ['none', 'static', 'dynamic'],
+                command = self.setvscrollmode,
+                menubutton_width = 8,
+        )
+        vmode.pack(side = 'left', padx = 5, pady = 3)
+        vmode.invoke('dynamic')
+
+        self.radio = Pmw.RadioSelect(parent, selectmode = 'multiple',
+            command = self.radioSelected)
+        self.radio.add('center', text = 'Keep centered vertically')
+        self.radio.pack(side = 'bottom')
+
+        buttonBox = Pmw.ButtonBox(parent)
+        buttonBox.pack(side = 'bottom')
+        buttonBox.add('add', text = 'Add a button', command = self.addButton)
+        buttonBox.add('yview', text = 'Show yview', command = self.showYView)
+        buttonBox.add('scroll', text = 'Page down', command = self.pageDown)
+
+        # Pack this last so that the buttons do not get shrunk when
+        # the window is resized.
+        self.sf.pack(padx = 5, pady = 3, fill = 'both', expand = 1)
+
+        self.frame = self.sf.interior()
+
+        self.row = 0
+        self.col = 0
+
+        for count in range(15):
+            self.addButton()
+
+    def sethscrollmode(self, tag):
+        self.sf.configure(hscrollmode = tag)
+
+    def setvscrollmode(self, tag):
+        self.sf.configure(vscrollmode = tag)
+
+    def sethflex(self, tag):
+        self.sf.configure(horizflex = tag)
+
+    def setvflex(self, tag):
+        self.sf.configure(vertflex = tag)
+
+    def addButton(self):
+        button = Tkinter.Button(self.frame,
+            text = '(%d,%d)' % (self.col, self.row))
+        button.grid(row = self.row, column = self.col, sticky = 'nsew')
+
+        self.frame.grid_rowconfigure(self.row, weight = 1)
+        self.frame.grid_columnconfigure(self.col, weight = 1)
+        if self.sf.cget('horizflex') == 'expand' or \
+                self.sf.cget('vertflex') == 'expand':
+            self.sf.reposition()
+
+        if 'center' in self.radio.getcurselection():
+            self.sf.update_idletasks()
+            self.centerPage()
+
+        if self.col == self.row:
+            self.col = 0
+            self.row = self.row + 1
+        else:
+            self.col = self.col + 1
+
+    def showYView(self):
+        print self.sf.yview()
+
+    def pageDown(self):
+        self.sf.yview('scroll', 1, 'page')
+
+    def radioSelected(self, name, state):
+        if state:
+            self.centerPage()
+
+    def centerPage(self):
+        # Example of how to use the yview() method of Pmw.ScrolledFrame.
+        top, bottom = self.sf.yview()
+        size = bottom - top
+        middle = 0.5 - size / 2
+        self.sf.yview('moveto', middle)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 February 2001 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ScrolledListBox.gif b/Pmw/Pmw_1_2/doc/ScrolledListBox.gif new file mode 100644 index 00000000..9a595618 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/ScrolledListBox.gif differ diff --git a/Pmw/Pmw_1_2/doc/ScrolledListBox.html b/Pmw/Pmw_1_2/doc/ScrolledListBox.html new file mode 100644 index 00000000..0c12d76e --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ScrolledListBox.html @@ -0,0 +1,379 @@ + + + + + + Pmw.ScrolledListBox reference manual + + + + +

Pmw.ScrolledListBox

+ +
+
+

Name

+

Pmw.ScrolledListBox() - + listbox with optional scrollbars +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A scrolled listbox consists of a standard listbox widget with optional + scrollbars which can be used to scroll the listbox. The + scrollbars can be dynamic, which means that a scrollbar will + only be displayed if it is necessary. That is, if the listbox + does not contain enough entries, the vertical scrollbar will be + automatically hidden and if the entries are not wide enough, the + horizontal scrollbar will be automatically hidden.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
dblclickcommand +
+This specifies a function to call when mouse button 1 is double + clicked over an entry in the listbox component. The default is None.

+ + +
+ +
hscrollmode +
+The horizontal scroll mode. If 'none', the horizontal scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+ +
items +
+Initialisation option. A tuple containing the initial items to be displayed by the + listbox component. The default is ().

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
scrollmargin +
+Initialisation option. The distance between the scrollbars and the listbox widget. The default is 2.

+ + +
+ +
selectioncommand +
+This specifies a function to call when mouse button 1 is single + clicked over an entry in the listbox component or if the <Space> + or <Return> key is hit while the listbox has focus. The default is None.

+ + +
+ +
usehullsize +
+Initialisation option. If true, the size of the megawidget is determined solely by the + width and height options of the hull component.

+

Otherwise, the size of the megawidget is determined by the width + and height of the listbox component, along with the size and/or + existence of the other components, such as the label, the + scrollbars and the scrollmargin option. All these affect the + overall size of the megawidget. The default is 0.

+ + + +
+ +
vscrollmode +
+The vertical scroll mode. If 'none', the vertical scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
horizscrollbar +
+The horizontal scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
listbox +
+The listbox widget which is scrolled by the scrollbars. By default, this component is a Tkinter.Listbox.

+ + +
+ +
vertscrollbar +
+The vertical scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +In addition, methods from the +Tkinter.Listbox class +are forwarded by this megawidget to the +listbox component. +

+ +
bbox(index)
+This method is explicitly forwarded to the listbox component's + bbox() method. Without this explicit forwarding, the bbox() + method (aliased to grid_bbox()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+ +
clear()
+Delete all items from the scrolled listbox. Equivalent to + setlist(()).

+ + +
+ +
get(first = None, last = None)
+This is the same as the get() method of the listbox component, + except that if first is None all list + elements are returned.

+ + +
+ +
getcurselection()
+Same as getvalue() method.

+ + +
+ +
getvalue()
+Return a list of the currently selected items of the listbox.

+ + +
+ +
setlist(items)
+Replace all the items of the listbox component with those + specified by the items sequence.

+ + +
+ +
setvalue(textOrList)
+Set the current selection for the scrolled list to textOrList.

+

If textOrList is a string, select only the list item specified.

+ +

Otherwise, select only the list items specified by textOrList, + which must be a sequence of strings.

+ + + +
+ +
size()
+This method is explicitly forwarded to the listbox component's + size() method. Without this explicit forwarding, the size() + method (aliased to grid_size()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the ScrolledListBox.
+        self.box = Pmw.ScrolledListBox(parent,
+                items=('Sydney', 'Melbourne', 'Brisbane'),
+                labelpos='nw',
+                label_text='Cities',
+                listbox_height = 6,
+                selectioncommand=self.selectionCommand,
+                dblclickcommand=self.defCmd,
+                usehullsize = 1,
+                hull_width = 200,
+                hull_height = 200,
+        )
+
+        # Create a group widget to contain the scrollmode options.
+        w = Pmw.Group(parent, tag_text='Scroll mode')
+        w.pack(side = 'bottom', padx = 5, pady = 5)
+
+        hmode = Pmw.OptionMenu(w.interior(),
+                labelpos = 'w',
+                label_text = 'Horizontal:',
+                items = ['none', 'static', 'dynamic'],
+                command = self.sethscrollmode,
+                menubutton_width = 8,
+        )
+        hmode.pack(side = 'top', padx = 5, pady = 5)
+        hmode.invoke('dynamic')
+
+        vmode = Pmw.OptionMenu(w.interior(),
+                labelpos = 'w',
+                label_text = 'Vertical:',
+                items = ['none', 'static', 'dynamic'],
+                command = self.setvscrollmode,
+                menubutton_width = 8,
+        )
+        vmode.pack(side = 'top', padx = 5, pady = 5)
+        vmode.invoke('dynamic')
+
+        buttonBox = Pmw.ButtonBox(parent)
+        buttonBox.pack(side = 'bottom')
+        buttonBox.add('yview', text = 'Show\nyview', command = self.showYView)
+        buttonBox.add('scroll', text = 'Page\ndown', command = self.pageDown)
+        buttonBox.add('center', text = 'Center', command = self.centerPage)
+
+        # Pack this last so that the buttons do not get shrunk when
+        # the window is resized.
+        self.box.pack(fill = 'both', expand = 1, padx = 5, pady = 5)
+
+        # Do this after packing the scrolled list box, so that the
+        # window does not resize as soon as it appears (because
+        # alignlabels has to do an update_idletasks).
+        Pmw.alignlabels((hmode, vmode))
+
+        # Add some more entries to the listbox.
+        items = ('Andamooka', 'Coober Pedy', 'Innamincka', 'Oodnadatta')
+        self.box.setlist(items)
+        self.box.insert(2, 'Wagga Wagga', 'Perth', 'London')
+        self.box.insert('end', 'Darwin', 'Auckland', 'New York')
+        index = list(self.box.get(0, 'end')).index('London')
+        self.box.delete(index)
+        self.box.delete(7, 8)
+        self.box.insert('end', 'Bulli', 'Alice Springs', 'Woy Woy')
+        self.box.insert('end', 'Wallumburrawang', 'Willandra Billabong')
+
+    def sethscrollmode(self, tag):
+        self.box.configure(hscrollmode = tag)
+
+    def setvscrollmode(self, tag):
+        self.box.configure(vscrollmode = tag)
+
+    def selectionCommand(self):
+        sels = self.box.getcurselection()
+        if len(sels) == 0:
+            print 'No selection'
+        else:
+            print 'Selection:', sels[0]
+
+    def defCmd(self):
+        sels = self.box.getcurselection()
+        if len(sels) == 0:
+            print 'No selection for double click'
+        else:
+            print 'Double click:', sels[0]
+
+    def showYView(self):
+        print self.box.yview()
+
+    def pageDown(self):
+        self.box.yview('scroll', 1, 'page')
+
+    def centerPage(self):
+        top, bottom = self.box.yview()
+        size = bottom - top
+        middle = 0.5 - size / 2
+        self.box.yview('moveto', middle)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 30 August 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ScrolledText.gif b/Pmw/Pmw_1_2/doc/ScrolledText.gif new file mode 100644 index 00000000..b766c95b Binary files /dev/null and b/Pmw/Pmw_1_2/doc/ScrolledText.gif differ diff --git a/Pmw/Pmw_1_2/doc/ScrolledText.html b/Pmw/Pmw_1_2/doc/ScrolledText.html new file mode 100644 index 00000000..1acbccc6 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ScrolledText.html @@ -0,0 +1,409 @@ + + + + + + Pmw.ScrolledText reference manual + + + + +

Pmw.ScrolledText

+ +
+
+

Name

+

Pmw.ScrolledText() - + text widget with optional scrollbars +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A scrolled text consists of a standard text widget with optional + scrollbars which can be used to scroll the text. The + scrollbars can be dynamic, which means that a scrollbar will + only be displayed if it is necessary. That is, if the text widget + does not contain enough text (either horizontally or vertically), + the scrollbar will be automatically hidden. If it is displayed, + the horizontal scrollbar is under the text widget. Similarly, if + it is displayed, the vertical scrollbar is to the right of the + text widget.

+ +

Row and column headers may also be displayed, which scroll in sync + with the text widget and may be useful when displaying tabular + data. To assist in ensuring that columns line up when using a + column header, a fixed width font should be used.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
borderframe +
+Initialisation option. If true, the borderframe component will be created. The default is 0.

+ + +
+ +
columnheader +
+Initialisation option. If true, the columnheader component will be created. The default is 0.

+ + +
+ +
hscrollmode +
+The horizontal scroll mode. If 'none', the horizontal scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
rowcolumnheader +
+Initialisation option. If true, the rowcolumnheader component will be created. The default is 0.

+ + +
+ +
rowheader +
+Initialisation option. If true, the rowheader component will be created. The default is 0.

+ + +
+ +
scrollmargin +
+Initialisation option. The distance between the scrollbars and the text widget. The default is 2.

+ + +
+ +
usehullsize +
+Initialisation option. If true, the size of the megawidget is determined solely by the + width and height options of the hull component.

+

Otherwise, the size of the megawidget is determined by the width + and height of the text component, along with the size and/or + existence of the other components, such as the label, the + scrollbars and the scrollmargin option. All these affect the + overall size of the megawidget. The default is 0.

+ + + +
+ +
vscrollmode +
+The vertical scroll mode. If 'none', the vertical scrollbar + will never be displayed. If 'static', the scrollbar will always + be displayed. If 'dynamic', the scrollbar will be displayed + only if necessary. The default is 'dynamic'.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
borderframe +
+A frame widget which snuggly fits around the text widget, to give + the appearance of a text border. It is created with a border so + that the text widget, which is created without a border, looks + like it has a border. By default, this component is a Tkinter.Frame.

+ + +
+ +
columnheader +
+A text widget with a default height of 1 displayed above the main + text widget and which scrolls horizontally in sync with the + horizontal scrolling of the main text widget. By default, this component is a Tkinter.Text. Its component group is Header.

+ + +
+ +
horizscrollbar +
+The horizontal scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
rowcolumnheader +
+A text widget displayed to the top left of the main text widget, + above the row header and to the left of the column header if they + exist. The widget is not scrolled automatically. By default, this component is a Tkinter.Text. Its component group is Header.

+ + +
+ +
rowheader +
+A text widget displayed to the left of the main text widget and + which scrolls vertically in sync with the vertical scrolling of + the main text widget. By default, this component is a Tkinter.Text. Its component group is Header.

+ + +
+ +
text +
+The text widget which is scrolled by the scrollbars. If the + borderframe option is true, this is created with a borderwidth + of 0 to overcome a known problem with text widgets: if a widget + inside a text widget extends across one of the edges of the text + widget, then the widget obscures the border of the text widget. + Therefore, if the text widget has no border, then this overlapping + does not occur. By default, this component is a Tkinter.Text.

+ + +
+ +
vertscrollbar +
+The vertical scrollbar. By default, this component is a Tkinter.Scrollbar. Its component group is Scrollbar.

+ + +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +In addition, methods from the +Tkinter.Text class +are forwarded by this megawidget to the +text component. +

+ +
appendtext(text)
+Add text to the end of the text component. Scroll to the + bottom of the text, but only if it was already visible before the + new text was added.

+ + +
+ +
bbox(index)
+This method is explicitly forwarded to the text component's + bbox() method. Without this explicit forwarding, the bbox() + method (aliased to grid_bbox()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+ +
clear()
+Delete all text from the text component.

+ + +
+ +
exportfile(fileName)
+Write the contents of the text component to the file fileName.

+ + +
+ +
get(first = None, last = None)
+This is the same as the get() method of the text component, + except that if first is None the entire + contents of the text widget are returned.

+ + +
+ +
getvalue()
+Return the entire contents of the text widget.

+ + +
+ +
importfile(fileName, where = 'end')
+Read the contents of the file fileName and insert into the + text component at the position given by where.

+ + +
+ +
settext(text)
+Same as setvalue() method.

+ + +
+ +
setvalue(text)
+Replace the entire contents of the text component with text.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+
+        # Create the ScrolledText with headers.
+        fixedFont = Pmw.logicalfont('Fixed')
+        self.st = Pmw.ScrolledText(parent,
+                # borderframe = 1,
+                labelpos = 'n',
+                label_text='ScrolledText with headers',
+                columnheader = 1,
+                rowheader = 1,
+                rowcolumnheader = 1,
+                usehullsize = 1,
+                hull_width = 400,
+                hull_height = 300,
+                text_wrap='none',
+                text_font = fixedFont,
+                Header_font = fixedFont,
+                Header_foreground = 'blue',
+                rowheader_width = 3,
+                rowcolumnheader_width = 3,
+                text_padx = 4,
+                text_pady = 4,
+                Header_padx = 4,
+                rowheader_pady = 4,
+        )
+
+        self.st.pack(padx = 5, pady = 5, fill = 'both', expand = 1)
+
+        funcs = 'atan cos cosh exp log log10 sin sinh sqrt tan tanh'
+        funcs = string.split(funcs)
+
+        # Create the header for the row headers
+        self.st.component('rowcolumnheader').insert('end', 'x')
+
+        # Create the column headers
+        headerLine = ''
+        for column in range(len(funcs)):
+            headerLine = headerLine + ('%-7s   ' % (funcs[column],))
+        headerLine = headerLine[:-3]
+        self.st.component('columnheader').insert('0.0', headerLine)
+
+        self.st.tag_configure('yellow', background = 'yellow')
+
+        # Create the data rows and the row headers
+        numRows = 50
+        tagList = []
+        for row in range(1, numRows):
+            dataLine = ''
+            x = row / 5.0
+            for column in range(len(funcs)):
+                value = eval('math.' + funcs[column] + '(' + str(x) + ')')
+                data = str(value)[:7]
+                if value < 0:
+                    tag1 = '%d.%d' % (row, len(dataLine))
+                    tag2 = '%d.%d' % (row, len(dataLine) + len(data))
+                    tagList.append(tag1)
+                    tagList.append(tag2)
+                data = '%-7s' % (data,)
+                dataLine = dataLine + data + '   '
+            dataLine = dataLine[:-3]
+            header = '%.1f' % (x,)
+            if row < numRows - 1:
+                dataLine = dataLine + '\n'
+                header = header + '\n'
+            self.st.insert('end', dataLine)
+            self.st.component('rowheader').insert('end', header)
+        apply(self.st.tag_add, ('yellow',) + tuple(tagList))
+
+        # Prevent users' modifying text and headers
+        self.st.configure(
+            text_state = 'disabled',
+            Header_state = 'disabled',
+        )
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 30 August 1998 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/ScrolledText_test.py b/Pmw/Pmw_1_2/doc/ScrolledText_test.py new file mode 100644 index 00000000..53a5ab48 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/ScrolledText_test.py @@ -0,0 +1,116 @@ +# Based on iwidgets2.2.0/tests/scrolledtext.test code. + +import Test +import Pmw + +Test.initialise() + +c = Pmw.ScrolledText + +def _testYView(doBottom): + w = Test.currentWidget() + top, bottom = w.yview() + if type(top) != type(0.0) or type(bottom) != type(0.0): + return 'bad type ' + str(top) + ' ' + str(bottom) + if doBottom: + if bottom != 1.0: + return 'bottom is ' + str(bottom) + else: + if top != 0.0: + return 'top is ' + str(top) + +kw_1 = {'labelpos': 'n', 'label_text': 'ScrolledText'} +tests_1 = ( + (c.pack, (), {'padx' : 10, 'pady' : 10, 'fill' : 'both', 'expand' : 1}), + (Test.num_options, (), 10), + (c.importfile, 'ScrolledText_test.py'), + ('hull_background', 'aliceblue'), + ('text_borderwidth', 3), + ('Scrollbar_borderwidth', 3), + ('hull_cursor', 'gumby'), + ('text_exportselection', 0), + ('text_exportselection', 1), + ('text_foreground', 'Black'), + ('text_height', 10), + ('text_width', 20), + ('text_insertbackground', 'Black'), + ('text_insertborderwidth', 1), + ('text_insertofftime', 200), + ('text_insertontime', 500), + ('text_insertwidth', 3), + ('label_text', 'Label'), + ('text_relief', 'raised'), + ('text_relief', 'sunken'), + ('Scrollbar_repeatdelay', 200), + ('Scrollbar_repeatinterval', 105), + ('vscrollmode', 'none'), + ('vscrollmode', 'static'), + ('vscrollmode', 'dynamic'), + ('hscrollmode', 'none'), + ('hscrollmode', 'static'), + ('hscrollmode', 'dynamic'), + ('Scrollbar_width', 20), + ('text_selectborderwidth', 2), + ('text_state', 'disabled'), + ('text_state', 'normal'), + ('text_background', 'GhostWhite'), + ('text_wrap', 'char'), + ('text_wrap', 'none'), + ('vscrollmode', 'bogus', 'ValueError: bad vscrollmode ' + + 'option "bogus": should be static, dynamic, or none'), + ('hscrollmode', 'bogus', 'ValueError: bad hscrollmode ' + + 'option "bogus": should be static, dynamic, or none'), + (c.cget, 'vscrollmode', 'bogus'), + (c.cget, 'hscrollmode', 'bogus'), + ('vscrollmode', 'dynamic'), + ('hscrollmode', 'dynamic'), + (c.insert, ('end', 'Hello there\n')), + (_testYView, 0), + (c.yview, ('moveto', 0.02)), + (c.yview, ('moveto', 0.04)), + (c.yview, ('moveto', 0.06)), + (c.yview, ('moveto', 0.08)), + (c.yview, ('moveto', 0.10)), + (c.yview, ('moveto', 0.12)), + (c.yview, ('moveto', 0.14)), + (c.yview, ('moveto', 0.16)), + (c.yview, ('moveto', 0.18)), + (c.yview, ('moveto', 0.20)), + (c.yview, ('moveto', 0.22)), + (c.yview, ('moveto', 0.24)), + (c.yview, ('moveto', 0.26)), + (c.yview, ('moveto', 0.28)), + (c.yview, ('moveto', 0.98)), + (_testYView, 1), + (c.yview, ('scroll', -1, 'page')), + (c.yview, ('scroll', -50, 'page')), + (_testYView, 0), + (c.yview, ('scroll', 1, 'page')), + (c.yview, ('scroll', 50, 'page')), + (_testYView, 1), + (c.clear, ()), + (c.get, (), '\n'), +) + +kw_2 = { + 'hscrollmode' : 'dynamic', + 'label_text' : 'Label', + 'labelpos' : 'n', + 'scrollmargin': 20, +} +tests_2 = ( + (c.pack, (), {'padx' : 10, 'pady' : 10, 'fill' : 'both', 'expand' : 1}), + (c.importfile, 'ScrolledText_test.py'), + ('text_relief', 'raised'), + ('text_relief', 'sunken'), +) + +alltests = ( + (tests_1, kw_1), + (tests_2, kw_2), +) + +testData = ((Pmw.ScrolledText, alltests),) + +if __name__ == '__main__': + Test.runTests(testData) diff --git a/Pmw/Pmw_1_2/doc/SelectionDialog.gif b/Pmw/Pmw_1_2/doc/SelectionDialog.gif new file mode 100644 index 00000000..1d6f3dd9 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/SelectionDialog.gif differ diff --git a/Pmw/Pmw_1_2/doc/SelectionDialog.html b/Pmw/Pmw_1_2/doc/SelectionDialog.html new file mode 100644 index 00000000..c4708232 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/SelectionDialog.html @@ -0,0 +1,281 @@ + + + + + + Pmw.SelectionDialog reference manual + + + + +

Pmw.SelectionDialog

+ +
+
+

Name

+

Pmw.SelectionDialog() - + selection dialog displaying a scrolled list +

+ + +
+

Inherits

+Pmw.Dialog
+
+

Description

+

+ The selection dialog is a dialog window which displays a scrolled + list which can be used to prompt the user for a value.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
borderx +
+Initialisation option. The padding to the left and right of the scrolled list. The default is 10.

+ + +
+ +
bordery +
+Initialisation option. The padding above and below the scrolled list. The default is 10.

+ + +
+ +
buttonboxpos +
+Initialisation option. Specifies on which side of the dialog window to place the button + box. Must be one of 'n', 's', 'e' or 'w'. The default is 's'.

+ + +
+ +
buttons +
+This must be a tuple or a list and specifies the names on the + buttons in the button box. The default is ('OK',).

+ + +
+ +
command +
+Specifies a function to call whenever a button in the button box + is invoked or the window is deleted by the window manager. The + function is called with a single argument, which is the name of + the button which was invoked, or None if the window was deleted + by the window manager.

+

If the value of command is not callable, the default behaviour + is to deactivate the window if it is active, or withdraw the + window if it is not active. If it is deactivated, deactivate() + is called with the button name or None as described above. The default is None.

+ + + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
defaultbutton +
+Specifies the default button in the button box. If the <Return> + key is hit when the dialog has focus, the default button will be + invoked. If defaultbutton is None, there will be no default + button and hitting the <Return> key will have no effect. The default is None.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
separatorwidth +
+Initialisation option. If this is greater than 0, a separator line with the specified + width will be created between the button box and the child site, + as a component named separator. Since the default border of the + button box and child site is raised, this option does not + usually need to be set for there to be a visual separation between + the button box and child site. The default is 0.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
buttonbox +
+This is the button box containing the buttons for the dialog. By + default it is created with the options + (hull_borderwidth = 1, hull_relief = 'raised'). By default, this component is a Pmw.ButtonBox.

+ + +
+ +
dialogchildsite +
+This is the child site for the dialog, which may be used to + specialise the megawidget by creating other widgets within it. By + default it is created with the options + (borderwidth = 1, relief = 'raised'). By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
scrolledlist +
+The scrolled list for the user to enter a value. By default, this component is a Pmw.ScrolledListBox.

+ + +
+ +
separator +
+If the separatorwidth initialisation option is non-zero, the + separator component is the line dividing the area between the + button box and the child site. By default, this component is a Tkinter.Frame.

+ + +
+
+

Component aliases

+Sub-components of components of this megawidget +may be accessed via the following aliases.

+
label +
+Alias for scrolledlist_label. +
+
listbox +
+Alias for scrolledlist_listbox. +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.Dialog. +In addition, methods from the +Pmw.ScrolledListBox class +are forwarded by this megawidget to the +scrolledlist component. +

+ +
bbox(index)
+This method is explicitly forwarded to the listbox component's + bbox() method. Without this explicit forwarding, the bbox() + method (aliased to grid_bbox()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+ +
size()
+This method is explicitly forwarded to the listbox component's + size() method. Without this explicit forwarding, the size() + method (aliased to grid_size()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the dialog.
+        self.dialog = Pmw.SelectionDialog(parent,
+            title = 'My SelectionDialog',
+            buttons = ('OK', 'Cancel'),
+            defaultbutton = 'OK',
+            scrolledlist_labelpos = 'n',
+            label_text = 'What do you think of Pmw?',
+            scrolledlist_items = ('Cool man', 'Cool', 'Good', 'Bad', 'Gross'),
+            command = self.execute)
+        self.dialog.withdraw()
+
+        # Create button to launch the dialog.
+        w = Tkinter.Button(parent, text = 'Show selection dialog',
+                command = self.dialog.activate)
+        w.pack(padx = 8, pady = 8)
+
+    def execute(self, result):
+        sels = self.dialog.getcurselection()
+        if len(sels) == 0:
+            print 'You clicked on', result, '(no selection)'
+        else:
+            print 'You clicked on', result, sels[0]
+        self.dialog.deactivate(result)
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/TextDialog.gif b/Pmw/Pmw_1_2/doc/TextDialog.gif new file mode 100644 index 00000000..4438828d Binary files /dev/null and b/Pmw/Pmw_1_2/doc/TextDialog.gif differ diff --git a/Pmw/Pmw_1_2/doc/TextDialog.html b/Pmw/Pmw_1_2/doc/TextDialog.html new file mode 100644 index 00000000..3f4995f4 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/TextDialog.html @@ -0,0 +1,301 @@ + + + + + + Pmw.TextDialog reference manual + + + + +

Pmw.TextDialog

+ +
+
+

Name

+

Pmw.TextDialog() - + a dialog displaying a scrolled text +

+ + +
+

Inherits

+Pmw.Dialog
+
+

Description

+

+ A text dialog is a dialog window which displays a text message to + the user along with one or more buttons to press.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
activatecommand +
+If this is callable, it will be called whenever the megawidget is + activated by a call to activate(). The default is None.

+ + +
+ +
borderx +
+Initialisation option. The padding to the left and right of the scrolled text. The default is 10.

+ + +
+ +
bordery +
+Initialisation option. The padding above and below the scrolled text. The default is 10.

+ + +
+ +
buttonboxpos +
+Initialisation option. Specifies on which side of the dialog window to place the button + box. Must be one of 'n', 's', 'e' or 'w'. The default is 's'.

+ + +
+ +
buttons +
+This must be a tuple or a list and specifies the names on the + buttons in the button box. The default is ('OK',).

+ + +
+ +
command +
+Specifies a function to call whenever a button in the button box + is invoked or the window is deleted by the window manager. The + function is called with a single argument, which is the name of + the button which was invoked, or None if the window was deleted + by the window manager.

+

If the value of command is not callable, the default behaviour + is to deactivate the window if it is active, or withdraw the + window if it is not active. If it is deactivated, deactivate() + is called with the button name or None as described above. The default is None.

+ + + +
+ +
deactivatecommand +
+If this is callable, it will be called whenever the megawidget is + deactivated by a call to deactivate(). The default is None.

+ + +
+ +
defaultbutton +
+Specifies the default button in the button box. If the <Return> + key is hit when the dialog has focus, the default button will be + invoked. If defaultbutton is None, there will be no default + button and hitting the <Return> key will have no effect. The default is None.

+ + +
+ +
master +
+This is used by the activate() method to control whether the + window is made transient during modal dialogs. See the + activate() method. The default is 'parent'.

+ + +
+ +
separatorwidth +
+Initialisation option. If this is greater than 0, a separator line with the specified + width will be created between the button box and the child site, + as a component named separator. Since the default border of the + button box and child site is raised, this option does not + usually need to be set for there to be a visual separation between + the button box and child site. The default is 0.

+ + +
+ +
title +
+This is the title that the window manager displays in the title + bar of the window. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
buttonbox +
+This is the button box containing the buttons for the dialog. By + default it is created with the options + (hull_borderwidth = 1, hull_relief = 'raised'). By default, this component is a Pmw.ButtonBox.

+ + +
+ +
dialogchildsite +
+This is the child site for the dialog, which may be used to + specialise the megawidget by creating other widgets within it. By + default it is created with the options + (borderwidth = 1, relief = 'raised'). By default, this component is a Tkinter.Frame.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Toplevel.

+ + +
+ +
scrolledtext +
+The scrolled text to contain the text for the dialog. By default, this component is a Pmw.ScrolledText.

+ + +
+ +
separator +
+If the separatorwidth initialisation option is non-zero, the + separator component is the line dividing the area between the + button box and the child site. By default, this component is a Tkinter.Frame.

+ + +
+
+

Component aliases

+Sub-components of components of this megawidget +may be accessed via the following aliases.

+
label +
+Alias for scrolledtext_label. +
+
text +
+Alias for scrolledtext_text. +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.Dialog. +In addition, methods from the +Pmw.ScrolledText class +are forwarded by this megawidget to the +scrolledtext component. +

+ +
bbox(index)
+This method is explicitly forwarded to the text component's + bbox() method. Without this explicit forwarding, the bbox() + method (aliased to grid_bbox()) of the hull would be invoked, + which is probably not what the programmer intended.

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        # Create the dialog.
+        dialog = Pmw.TextDialog(parent, scrolledtext_labelpos = 'n',
+                title = 'My TextDialog',
+                defaultbutton = 0,
+                label_text = 'Lawyer jokes')
+        dialog.withdraw()
+        dialog.insert('end', jokes)
+        dialog.configure(text_state = 'disabled')
+
+        # Create button to launch the dialog.
+        w = Tkinter.Button(parent, text = 'Show text dialog',
+                command = dialog.activate)
+        w.pack(padx = 8, pady = 8)
+
+jokes = """
+Q: What do you call 5000 dead lawyers at the bottom of the ocean?
+A: A good start!
+
+Q: How can you tell when a lawyer is lying?
+A: His lips are moving.
+
+Q: Why won't sharks attack lawyers?
+A: Professional courtesy.
+
+Q: What do have when a lawyer is buried up to his neck in sand?
+A: Not enough sand.
+
+Q: How do you get a lawyer out of a tree?
+A: Cut the rope.
+
+Q: What is the definition of a shame (as in "that's a shame")?
+A: When a bus load of lawyers goes off a cliff.
+
+Q: What is the definition of a "crying shame"?
+A: There was an empty seat.
+
+Q: What do you get when you cross the Godfather with a lawyer?
+A: An offer you can't understand.
+
+Q. What do lawyers use as contraceptives?
+A. Their personalities.
+
+Q. What's brown and black and looks good on a lawyer?
+A. A doberman.
+
+Q. Why are lawyers buried 12 feet underground?
+A. Deep down their good.
+
+Q. What's the difference between a catfish and a lawyer?
+A. One's a slimy scum-sucking scavenger, the other is just a fish.
+
+"""
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 18 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/TimeCounter.gif b/Pmw/Pmw_1_2/doc/TimeCounter.gif new file mode 100644 index 00000000..26cbdba5 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/TimeCounter.gif differ diff --git a/Pmw/Pmw_1_2/doc/TimeCounter.html b/Pmw/Pmw_1_2/doc/TimeCounter.html new file mode 100644 index 00000000..6fbdea33 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/TimeCounter.html @@ -0,0 +1,363 @@ + + + + + + Pmw.TimeCounter reference manual + + + + +

Pmw.TimeCounter

+ +
+
+

Name

+

Pmw.TimeCounter() - + counter for display and input of time +

+ + +
+

Inherits

+Pmw.MegaWidget
+
+

Description

+

+ A time counter is similar to a regular Pmw.Counter except that the + user may increment and decrement the hours, minutes and seconds + individually.

+ +

+ + +
+

Options

+Options for this megawidget and its base +classes are described below.

+ +
autorepeat +
+If true, the counter will continue to count up or down while an + arrow button is held pressed down. The default is 1.

+ + +
+ +
buttonaspect +
+Initialisation option. Specifies the width of the arrow buttons as a proportion of their + height. Values less than 1.0 will produce thin arrow buttons. + Values greater than 1.0 will produce fat arrow buttons. The default is 1.0.

+ + +
+ +
command +
+This specifies a function to call whenever the <Return> key is + pressed in one of the entry fields or invoke() is called. The default is None.

+ + +
+ +
initwait +
+Specifies the initial delay (in milliseconds) before a depressed + arrow button automatically starts to repeat counting. The default is 300.

+ + +
+ +
labelmargin +
+Initialisation option. If the labelpos option is not None, this specifies the + distance between the label component and the rest of the + megawidget. The default is 0.

+ + +
+ +
labelpos +
+Initialisation option. Specifies where to place the label component. If not + None, it should be a concatenation of one or two of the + letters 'n', 's', 'e' and 'w'. The first letter + specifies on which side of the megawidget to place the label. + If a second letter is specified, it indicates where on that + side to place the label. For example, if labelpos is 'w', + the label is placed in the center of the left hand side; if + it is 'wn', the label is placed at the top of the left + hand side; if it is 'ws', the label is placed at the + bottom of the left hand side.

+

If None, a label component is not created. The default is None.

+ + + +
+ +
max +
+Specifies the maximum acceptable time in the form "HH:MM:SS", or + None if no maximum checking should be performed. The default is None.

+ + +
+ +
min +
+Specifies the minimum acceptable time in the form "HH:MM:SS", or + None if no minimum checking should be performed. The default is None.

+ + +
+ +
padx +
+Initialisation option. Specifies how much wider to make each column than the default + width (where a column consists of two arrows and an entry field). + The entry fields expand to fill the extra space, but the arrow + buttons are centered in the available space. The default is 0.

+ + +
+ +
pady +
+Initialisation option. Specifies how much higher to make each row of arrow buttons than + the default hight. The arrow buttons are centered in the + available space. The default is 0.

+ + +
+ +
repeatrate +
+Specifies the delay (in milliseconds) between automatic counts + while an arrow button is held pressed down. The default is 50.

+ + +
+ +
value +
+Initialisation option. Specifies the initial contents of the time counter, in the form + "HH:MM:SS". If this is None, the current time is used as the + initial contents. The default is None.

+ + +
+
+

Components

+Components created by this megawidget and its base +classes are described below.

+ +
downhourarrow +
+The arrow button used for decrementing the hour field. By default, this component is a Tkinter.Canvas. Its component group is Arrow.

+ + +
+ +
downminutearrow +
+The arrow button used for decrementing the minute field. By default, this component is a Tkinter.Canvas. Its component group is Arrow.

+ + +
+ +
downsecondarrow +
+The arrow button used for decrementing the second field. By default, this component is a Tkinter.Canvas. Its component group is Arrow.

+ + +
+ +
frame +
+If the label component has been created (that is, the labelpos + option is not None), the frame component is created to act as + the container of the entry fields and arrow buttons. If there is + no label component, then no frame component is created and the + hull component acts as the container. In either case the border + around the container of the entry fields and arrow buttons will be + raised (but not around the label). By default, this component is a Tkinter.Frame.

+ + +
+ +
hourentryfield +
+The entry field where the hours are entered and displayed. By default, this component is a Pmw.EntryField.

+ + +
+ +
hull +
+This acts as the body for the entire megawidget. Other components + are created as children of the hull to further specialise this + class. By default, this component is a Tkinter.Frame.

+ + +
+ +
label +
+If the labelpos option is not None, this component is + created as a text label for the megawidget. See the + labelpos option for details. Note that to set, for example, + the text option of the label, you need to use the label_text + component option. By default, this component is a Tkinter.Label.

+ + +
+ +
minuteentryfield +
+The entry field where the minutes are entered and displayed. By default, this component is a Pmw.EntryField.

+ + +
+ +
secondentryfield +
+The entry field where the seconds are entered and displayed. By default, this component is a Pmw.EntryField.

+ + +
+ +
uphourarrow +
+The arrow button used for incrementing the hour field. By default, this component is a Tkinter.Canvas. Its component group is Arrow.

+ + +
+ +
upminutearrow +
+The arrow button used for incrementing the minute field. By default, this component is a Tkinter.Canvas. Its component group is Arrow.

+ + +
+ +
upsecondarrow +
+The arrow button used for incrementing the second field. By default, this component is a Tkinter.Canvas. Its component group is Arrow.

+ + +
+
+

Component aliases

+Sub-components of components of this megawidget +may be accessed via the following aliases.

+
hourentry +
+Alias for hourentryfield_entry. +
+
minuteentry +
+Alias for minuteentryfield_entry. +
+
secondentry +
+Alias for secondentryfield_entry. +
+
+ +

Methods

+Only methods specific to this megawidget are described below. +For a description of its inherited methods, see the +manual for its base class +Pmw.MegaWidget. +

+ +
decrement(seconds = 1)
+Decrement the time by seconds seconds.

+ + +
+ +
getint()
+Return the currently displayed time as a number of seconds.

+ + +
+ +
getstring()
+Same as getvalue() method.

+ + +
+ +
getvalue()
+Return the currently displayed time as a string in the form + "HH:MM:SS".

+ + +
+ +
increment(seconds = 1)
+Increment the time by seconds seconds.

+ + +
+ +
invoke()
+Invoke the command specified by the command option as if the + <Return> key had been pressed.

+ + +
+ +
setvalue(text)
+Set the contents of the time counter, where text must be in the + form "HH:MM:SS".

+ + +
+
+

Example

+The image at the top of this manual is a snapshot +of the window (or part of the window) produced +by the following code.

+
+class Demo:
+    def __init__(self, parent):
+        self._time = Pmw.TimeCounter(parent,
+                labelpos = 'w',
+                label_text = 'HH:MM:SS',
+                min = '00:00:00',
+                max = '23:59:59')
+        self._time.pack(padx=10, pady=5)
+
+        button = Tkinter.Button(parent, text = 'Show', command = self.show)
+        button.pack()
+
+    def show(self):
+        stringVal = self._time.getstring()
+        intVal =  self._time.getint()
+        print stringVal + '  (' + str(intVal) + ')'
+
+
+
+
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home +
Manual page last reviewed: 25 May 2002 +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/blue_line.gif b/Pmw/Pmw_1_2/doc/blue_line.gif new file mode 100644 index 00000000..2063df02 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/blue_line.gif differ diff --git a/Pmw/Pmw_1_2/doc/blueball.gif b/Pmw/Pmw_1_2/doc/blueball.gif new file mode 100644 index 00000000..013183af Binary files /dev/null and b/Pmw/Pmw_1_2/doc/blueball.gif differ diff --git a/Pmw/Pmw_1_2/doc/bugs.html b/Pmw/Pmw_1_2/doc/bugs.html new file mode 100644 index 00000000..f46e8e9e --- /dev/null +++ b/Pmw/Pmw_1_2/doc/bugs.html @@ -0,0 +1,378 @@ + + + + + + List of known bugs + + + + +

List of known bugs

+ +

+This is a list of some of the known bugs in Pmw. If you fix any of +these, please let the maintainer (gregm@iname.com) know.

+
  • Under the Enlightenment window manager, if show() is called when + a window is already displayed (and is not obscured by other + windows), then the application will hang for two seconds. This + is either a bug in Tcl/Tk or in Enlightenment. See the comment + in the Tk function WaitForConfigureNotify() in the Tk source + file tk8.3.2/unix/tkUnixWm.c:

    +
     /*
    +  * One more tricky detail about this procedure.  In some cases the
    +  * window manager will decide to ignore a configure request (e.g.
    +  * because it thinks the window is already in the right place).
    +  * To avoid hanging in this situation, only wait for a few seconds,
    +  * then give up.
    +  */
    + + +
  • +
  • On NT, Pmw.MenuBar does not display message bar help for menu + items. It seems that Tk menu widgets do not support <Motion> + events on MS. This probably is an issue that should be taken up + with the Tcl/Tk people. (Reported by Stefan Schone. Pmw.0.7)

    + +
  • +
  • Run the CounterDialog.py demo, select the show dialog button and + press ok. Now exit the dialog (either with the exit button or + the close box). The following error appears:

    +
     Menu ID 256 is already in use!Fatal Python Error: Tcl/Tk panic
    + +

    This may be a problem with Mac version of Tk. (Reported by + Anthony Wilson.)

    + + +
  • +
  • Pmw.Balloons bind to widgets and canvas items. This means that + bindings made by other users are deleted when the balloon makes + its bindings. (For example, the "Delete" canvas item in the + Balloon demo overrides that <ButtonPress> binding and so that + balloon is not withdrawn when the mouse button is pressed over + the item.)

    +

    The obvious solution is for Pmw.Balloon to add its bindings with + a +. But this would make the unbind and tagunbind methods + inconsistent - they would remove all bindings, not just the ones + added by the balloon. A better way would be for the balloon to + add a bindtag to each widget`s bindtag list - then it would not + upset any other bindings and it could be deleted cleanly. + (Reported by Joe Saltiel)

    + + +
+ +
 import Tkinter
+ import Pmw
+ 
+ def foo(event):
+     print '<Enter> event on text'
+ 
+ root = Pmw.initialise()
+ balloon = Pmw.Balloon()
+ 
+ canvas = Tkinter.Canvas()
+ canvas.pack()
+ 
+ text1 = canvas.create_text(50, 50, text = 'hello
+there')
+ 
+ # As is, the balloon does not appear over the text, but foo
+ # is called.  Swap the following two lines and the balloon
+ # appears but foo will not be called.
+ canvas.tag_bind(text1, "<Enter>", foo)
+ balloon.tagbind(canvas, text1, 'text 1 help')
+ 
+ root.mainloop()
+
  • In Pmw.Balloon, the balloon should not be withdrawn when the + pointer leaves a widget or item and it immediatly enters another + widget or item with balloon help. Instead, the balloon should + be moved and its contents changed immediately.

    + +
  • +
  • When a Pmw.Balloon is bound to a canvas item, moving the item + becomes very slow. (Reported by Joe Saltiel)

    +
     > Second, after I fixed my ordering problem I noticed, there
    + > is a pretty big delay in updating widgets that have balloon
    + > messages bound to them.  (For example dragging a box across
    + > a screen, the box has a delayed reaction.) I believe this is
    + > due to some of the timing functions used in PmwBalloon, I am
    + > not sure if there is a way around it.  I set all timers to
    + > zero, and still had the problem.
    + + +
  • +
  • When running Pmw demos under ptui the busy cursor does not + appear.

    + +
  • +
  • If a combobox has a horizontal scrollbar and it displays its + listbox above the entry, then it is misplaced.

    + +
  • +
  • Bug in Pmw.PanedWidget: repeat by creating new panes in Demo - + existing panes jump to the right 1 or 2 pixels.

    + +
  • +
  • Bug in Pmw.PanedWidget: repeat by setting hull_borderwidth to + 20 in demo - initial drag jumps to right by about 20 pixels. + Also right hand side border is missing. (Fix may be similar to + method used in Pmw.ScrolledFrame to give canvas border.)

    + +
  • +
  • Fix ButtonRelease events so they do not trigger without a + corresponding ButtonPress event.

    +

    From Joe Saltiel: I was playing around with a scrolledlistbox + and tkFileDialog. When I have the dialog open above the list + box and I doubleclick on it, I invoke the selectioncmd of the + listbox as well as the tkFileDialog box, should this be + happening?

    + +

    Attached is small sample program you can try. To get the bug to + show you must do two things. First, when you open the file + dialog box, make sure the item you are going to select if + over(above) the scrolledlistbox. Second, you have to double + click on that item. If you single click and hit "Open" you do + not get the bug. Nor do you get it unless the file you click on + is directly over the clickable region of the scrolledlist box.

    +
     import Tkinter
    + import Pmw
    + import tkFileDialog
    + import string 
    + 
    + def askOpen():
    +     file = tkFileDialog.askopenfile(filetypes=[("all files", "*")])  
    +     print file
    + 
    + def printMe():
    +     print "Me"
    + 
    + root = Tkinter.Tk()
    + Pmw.initialise(root)
    + 
    + frame1 = Tkinter.Frame(root)
    + lst = string.split("abc def ghi jkl mno pqr stu vwx yz")
    + lstbox = Pmw.ScrolledListBox(frame1, items=lst, selectioncommand=printMe)
    + lstbox.grid(row=0, column=0, columnspan=2)
    + Tkinter.Button(frame1, text='open', command=askOpen).grid(row=1, column=0)
    + Tkinter.Button(frame1, text='exit', command=root.destroy).grid(row=1, column=1)
    + frame1.pack()
    + 
    + root.mainloop()
    + + +

    Response: I have found where the problem is but I am not sure + how to fix it. It appears that the tkFileDialog box closes on a + ButtonPress event. The corresponding ButtonRelease event is + then sent to whichever widget is under the cursor at the time of + the Release. I have reproduced the problem with a Tcl-only + script:

    +
     listbox .l
    + .l insert 0 1 2 3 4
    + bind .l <ButtonRelease-1> {puts AAAGGHHH!}
    +
    + button .b -text open -command tk_getOpenFile
    + pack .l .b
    + + +

    If you do a quick Press-Release-Press over the file dialog, it + is withdrawn. If you then keep the mouse button down and move + the mouse around, you will see that the button and the listbox + still respond to it. If you do the final button Release over + the listbox, its <ButtonRelease-1> binding is invoked.

    + +

    I think the correct solution is to modify Pmw to be very careful + when to accept ButtonRelease events. It will need to also bind + to ButtonPress events and make sure that it gets a Press before + it accepts the Release. I'll try to do the change as soon as + possible, but the code involved is fairly complex so I it may + take a little time.

    + + +
  • +
  • Investigate bug in Tk8.0: When a dialog pops up over the + pointer then the keyboard focus is not set and so <Return> does + not invoke default button.

    + +
  • +
  • Under both X and NT, the arrows in the timecounter, counter and + combobox do not match the scrollbar arrows.

    + +
  • +
  • Pmw.Group does not work correctly when the tag is a compound + widget. The tag is placed such that the top of the tag is cut + off. (Reported by Peter Stoehr.)

    +
     import Tkinter
    + import Pmw
    + 
    + root = Tkinter.Tk()
    + Pmw.initialise(root, fontScheme = 'pmw1')
    + exitButton = Tkinter.Button(root, text = 'Exit', command = root.destroy)
    + exitButton.pack(side = 'bottom')
    + 
    + def makeGroup(tagClassName):
    +     tagClass = eval(tagClassName)
    +     group = Pmw.Group(
    +         tag_pyclass = tagClass,
    +         hull_background = 'red',
    +         groupchildsite_background = 'blue',
    +     )
    +     group.pack(fill = 'both', expand = 1, padx = 6, pady = 6)
    +     child = Tkinter.Label(group.interior(),
    +         text = 'Group with tag ' + tagClassName,
    +         background = 'aliceblue',
    +     )
    +     child.pack(padx = 10, pady = 5, expand = 1, fill = 'both')
    +
    +     return group
    + 
    + grp1 = makeGroup('Pmw.EntryField')
    + grp2 = makeGroup('Pmw.ComboBox')
    + grp3 = makeGroup('Tkinter.Entry')
    + 
    + root.mainloop()
    + +

    Also, Pmw.Group does not resize correctly if the simple widget + changes size. For example:

    +
     grp3.configure(tag_font = ('Helveltica', '-160'))
    + + + +
  • +
  • Bug(s) in PmwScrolledCanvas. There is a bug in 0.8.1 + PmwScrolledCanvas._setRegion. If there are no objects in the + canvas, then error occurs on len(region) because region is None. + Below is an attempt to fix it. Click on Show, then on Delete. + The window then continuously resizes. If the ScrolledCanvas is + created with canvasmargin = 0, the problem goes away. (Reported + by Anders Henja.)

    +
     import Tkinter
    + import Pmw
    + 
    + def _setRegion(self):
    +     # Attempt to fix PmwScrolledCanvas._setRegion.
    +     self.setregionTimer = None
    + 
    +     region = self._canvas.bbox('all')
    +     canvasmargin = self['canvasmargin']
    +     if region is None:
    +         region = (0, 0, 0, 0)
    +     region = (region[0] - canvasmargin, region[1] - canvasmargin,
    +         region[2] + canvasmargin, region[3] + canvasmargin)
    +     self._canvas.configure(scrollregion = region)
    + 
    + def show():
    +     canvas.component('canvas').delete('all')
    +     canvas.create_oval(0, 0, 800, 600, fill = 'red')
    +     canvas.configure(canvas_width = 600, canvas_height = 450)
    +     canvas.resizescrollregion()
    + 
    + def delete():
    +     canvas.component('canvas').delete('all')
    +     canvas.configure(canvas_width = 0, canvas_height = 0)
    +     canvas.resizescrollregion()
    + 
    + root=Tkinter.Tk()
    + Pmw.initialise(root)
    + 
    + buttonbox=Pmw.ButtonBox()
    + buttonbox.pack(fill='x',side='bottom',padx=5,pady=5)
    + buttonbox.add('Show',command=show)
    + buttonbox.add('Delete',command=delete)
    + buttonbox.alignbuttons()
    + 
    + canvas=Pmw.ScrolledCanvas(canvasmargin=2)
    + canvas.__class__._setRegion = _setRegion
    + canvas.pack(fill='both',side='right',expand=1)
    + 
    + root.mainloop()
    + + +
  • +
  • Bug in Pmw.Dialog: if defaultbutton is configured before + buttons during self.initialiseoptions() (that is if + self._constructorKeywords.keys() returns a different order), + then setdefault() fails.

    + +
  • +
  • Bugs in Tk which affect Pmw.MainMenuBar:

    +
    • Extra bindings assigned to a Tkinter.Menu widget using + bindtags have no effect. Hence the method used in + Pmw.MenuBar for status help (bind_class followed by + bindtags) does not work and therefore binding to the menu + widget is used instead.

      + +
    • +
    • The 'active' tag for the index() method of Tkinter.Menu + always returns None. Hence, in the menu widget motion + binding, event.y and the '@' format is used instead, for + all menus except the toplevel main menu.

      + +
    • +
    • For the toplevel main menu, event.x must be used for the + index() method, but it returns the wrong index. It + appears that the Tk widget is assuming vertical layout + to calculate distances, rather than horizontal.

      + +
    • +
    • For toplevel main menus, several Tk commands, such as + winfo_height(), do not work. This prevents the use of + balloon help for Pmw.MainMenuBar.

      + +
    + +
  • +
  • Bug in Pmw.ComboBox: Tab to combobox arrow, use up/down arrow + keys to change selection, hit return, nothing happens, <Shift + Tab> to entry window, hit return, combobox changes

    +
    • actually, it would be better if you could not tab to + the arrow, only the entry field, like the Pmw.Counter.

      + +
    • +
    • the problem is if the entry field is not editable, what to + do then?

      + +
    + +
  • +
  • Bug in TimeCounter: Arrow keys don't work when focus is on entry.

    + +
  • +
  • Bug in Pmw.NoteBook: The size of the tab does not change when + the text value changes

    + +
  • +
  • Bug in Pmw.NoteBook: The name of the tab components has a "-" sign + in it, which means that component options can not be used in the + configure command. Eg:

    +
     n = Pmw.NoteBook()
    + p = n.add('page1')
    + n.configure(page1_background = 'red')   # works
    + n.configure(page1-tab_background = 'red')   # fail, must do this:
    + n.component('page1-tab').configure(background = 'red')   # works
    + + +
+

+ + + + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/changes.html b/Pmw/Pmw_1_2/doc/changes.html new file mode 100644 index 00000000..f3dd6402 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/changes.html @@ -0,0 +1,1741 @@ + + + + + + Changes to Pmw + + + + +

Changes to Pmw

+ +

+ 6 January 1997

+ +
  • Release of version 0.1

    + +
+

14 February 1997

+ +
  • Fixed bug in Counter demo for the Macintosh - the maximum size of an + integer is smaller than the value returned by time.time().

    + +
  • +
  • Fixed bug in Grid demo for Tk 4.2 - grid_bbox returns garbage if it is + called without update_idletasks. Also, grid_bbox can only have two + arguments in Tk 4.1.

    + +
  • +
  • Modified ScrolledText demo so that the text widget contains enough text + to require a vertical scrollbar.

    + +
  • +
  • Changes to PmwBase:

    +
    • Prefixed the name of several private variables with a double underscore.

      + +
    • +
    • Added symbolic constants for the indexes into an optionInfo list.

      + +
    • +
    • Changed names of several methods and variables to be more descriptive.

      + +
    • +
    • Removed options() method.

      + +
    • +
    • Simplified configuration option data structures. Modified option + handling code so that default options are set correctly. If an + option is created before initialise() is called then initialise() + checks if the option is set by the keyword arguments to + initialise(). If not, then it is given the value found in the + Tk option database, if a value exists, or the default value. If an + option is created after initialise() is called, then it is given the + value found in the Tk option database, if a value exists, or the + default value.

      + +
    + +
  • +
  • Replaced usage of self._hull in megawidgets by interior() method.

    + +
  • +
  • Added autoclear option to ComboBox.

    + +
  • +
  • Fixed bug in ComboBox - fast clicking on the arrow button could result + in an attempt to grab a window that was not yet visible.

    + +
  • +
  • Added "sys.exc_traceback = None" to the except clauses of all try + statements so that references to objects in the stack trace would not + be left.

    + +
  • +
  • Added takefocus option to PushButton.

    + +
  • +
  • Modified the getcurselection() method of ScrolledListBox so that it + returns a string if the selection mode is 'single' or 'browse', rather + than a tuple with one element. This also affects methods forwarded and + derived from ScrolledListBox.

    + +
  • +
  • Modified ScrolledListBox so that it avoids unnecessary updates by + using idle timer.

    + +
  • +
  • Modified ScrolledText to use grid instead of pack.

    + +
  • +
  • Added shutdown() function to Tk module to clean up all references to + the Tcl interpreter and then delete it.

    + +
  • +
  • Fixed bug in Tk module for the Macintosh - update() was being called in + initialise() before the Tcl interpreter was created.

    + +
+

14 February 1997

+ +
  • Version 0.1.1 completed and released internally.

    + +
+

6 March 1997

+ +
  • Pmw now uses the standard Tkinter module. The Tk module has been + dropped. This means that the Tk module functions such as after, + bell, bind, update, etc, are no longer available and the equivalent + Tkinter methods should be used.

    + +
  • +
  • To restore some of the features of the Tk module, Pmw.initialise() + now adds run-time hooks into Tkinter to get notification of when Tk + widgets are created and destroyed. It also modifies the CallWrapper + class so that errors during callbacks and bindings can be displayed + in a window. If Pmw.initialise() is not called, Tkinter is not + modified and these features are not available.

    + +
  • +
  • If a Tk widget which is acting as the hull of a megawidget is + destroyed, then the megawidget is destroyed as well. This can + only happen if Pmw.initialise() is called.

    + +
  • +
  • Pmw.initialise() now takes the Tkinter root as its argument.

    + +
  • +
  • The parent of megawidgets now defaults to the Tk root. Previously, + the parent of non-toplevel megawidgets had to be given.

    + +
  • +
  • Added PmwBase.tracetk() function to get trace of calls to the Tcl + interpreter for debugging.

    + +
  • +
  • Added functions to PmwBase to display a busy cursor over the + application such as when a modal dialog is displayed or it is + blocked doing a long calculation. Uses busy command of the blt + extension, if present.

    + +
  • +
  • Created a nifty new demo which demonstrates most of the megawidgets + in a convenient way.

    + +
  • +
  • Added a TextDialog.

    + +
  • +
  • Added functionality to handle the grabbing of nested modal dialogs + correctly.

    + +
  • +
  • Added an activatecommand option to Dialog which allows, for example, + the PromptDialog widget to set the keyboard focus when it is + activated.

    + +
  • +
  • Added tests for Counter and logicalfont.

    + +
  • +
  • The ScrolledListBox selectioncommand is no longer given the widget + as its first argument.

    + +
  • +
  • Several method, function and component names were changed, to be + consistent with the coding conventions.

    + +
  • +
  • Some of the effects of moving from the Tk module to Tkinter are:

    +
    • The Tk module used to exit if there were no non-root toplevel + windows shown. This is no longer the case and so the application + must handle this explicitly, particularly if the root window is + withdrawn and the last non-root toplevel is deleted by the window + manager.

      + +
    • +
    • The Tk module bind functions and methods used to take a noEvent + argument to indicate that the Tk event should not be passed to the + callback. Tkinter does not support this.

      + +
    • +
    • The Tk module initialise() function should be replaced by + "root = Tkinter.Tk()" and root should be used instead of "Tk.Root()"

      + +
    • +
    • The Tk module quit() function should be replace by "root.destroy()".

      + +
    • +
    • Toplevels are not hidden when created. To be consistent, + MegaToplevels are not hidden either.

      + +
    • +
    • The hide and show methods are not available for Tkinter Toplevels, + only MegaToplevels

      + +
    • +
    • There is no grid_configure method.

      + +
    • +
    • Tkinter.Canvas.coords() returns a python list, not a tuple.

      + +
    • +
    • The Tkinter cget and configure widget methods always return + strings for the option values. The Tk module used to convert the + string to the appropriate python type (such as string, integer, + float, Variable, Image, callback function).

      + +
    • +
    • Tkinter Menu and Toplevel classes incorrectly have a pack method.

      + +
    • +
    • Menu class has no geometry method.

      + +
    • +
    • Canvas focus returns '' rather than None.

      + +
    • +
    • Text mark_gravity returns '' rather than None.

      + +
    + +
+

13 March 1997

+ +
  • Release of version 0.2

    + +
+

17 March 1997

+ +
  • Set default WM_DELETE_WINDOW protocol of Tkinter.Toplevel to + destroy() and removed duplicated protocol request from all demos.

    + +
  • +
  • Modified text of ShowBusy demo to indicate that busy cursor will + only be seen if the BLT extension is present.

    + +
  • +
  • Replaced call to update() in PmwLabeledWidget.py with update_idletasks().

    + +
  • +
  • Changed name of PromptDialog component from 'entry' to 'entryfield'.

    + +
+

28 April 1997

+ +
  • Version 0.3 released internally

    + +
+

19 August 1997

+ +
  • Many changes made (see the version 0.4 porting guide for + more details).

    + +
  • +
  • The option propagation mechanism that iwidgets uses is too + cumbersome, too hard to understand and, in python, too slow. + Developed a new mechanism which is more explicit in naming + options. This resulted in most options which were simply + propagated to components being removed. Removed keep(), rename() + and ignore() methods and "usual" options.

    + +
  • +
  • For speed, Pmw no longer queries the Tk option database for + default values for megawidget options. Hence, resource names and + classes do not need to be supplied when creating options and + None is returned for the resource name and class when using + configure() to query the options. Option "types" no longer + used.

    + +
  • +
  • Changed method and component names to be more consistent.

    + +
  • +
  • Replaced most uses of pack() with grid().

    + +
  • +
  • Megawidgets no longer inherit from LabeledWidget. Instead they + call createlabel() to optionally create the label component.

    + +
  • +
  • Removed child site from EntryField and rewrote ComboBox + accordingly.

    + +
  • +
  • Wrote lots more documentation, including automatically generated + reference manuals.

    + +
  • +
  • Removed PushButton and rewrote ButtonBox to directly create + Tkinter.Buttons rather than PushButtons.

    + +
  • +
  • Added initialisation options - options which can be set at + creation time but not later using configure().

    + +
  • +
  • Added aliases for components.

    + +
  • +
  • Modified the base classes so that during option configuration, + components are configured before configuration called functions + are called.

    + +
  • +
  • Added several more megawidgets.

    + +
  • +
  • Added interface to BLT graph and vector commands.

    + +
  • +
  • Created PmwLazy module for lazy importing of Pmw - avoids loading + megawidgets which are not used.

    + +
  • +
  • Added several more functions for handling color and fonts.

    + +
  • +
  • Replaced Counter and EntryField time with timeN and time24

    + +
  • +
  • Pmw.initialise() will now create Tkinter.Tk if not given root.

    + +
+

1 September 1997

+ +
  • Release of version 0.4

    + +
+

5 September 1997

+ +
  • Modified the base classes so that the Tk option database resource + class of megawidgets can be overridden in the call to the + constructor using the hull_class option.

    + +
  • +
  • The separators in Pmw.PanedWidget are now active - they can be + grabbed, like the handles, and moved around. The cursor now + changes to the correct left/right or up/down cursor when over a + separator or handle. (Clemens Hintze)

    + +
  • +
  • Fixed bug in MessageInfo demo Dismiss button. If it is invoked, + an error occurs saying "not enough arguments". (Mark Colclough)

    + +
+

9 September 1997

+ +
  • Added the useTkOptionDb argument to Pmw.initialise which + specifies that the initial values of megawidget options are to be + set by querying the Tk option database.

    + +
  • +
  • When used to query options, the configure() method now returns the + resource class and name of the options.

    + +
+

19 September 1997

+ +
  • Changed functions datestringtoint() and timestringtoint() to + datestringtojdn() and timestringtoseconds(). Changed return value + of datestringtojdn() to be Julian Day Numbers rather than seconds + since the epoch.

    + +
  • +
  • Fixed a bug in the date Counter due to use of time.timezone, by + replacing, when calculating date increments, calls to the time + module with calls to datestringtojdn().

    + +
  • +
  • Added century pivot year (setyearpivot function) to Counter date + datatypes to handle two-digit years.

    + +
  • +
  • Added date_dmy4, date_mdy4 and date_y4md datatypes to Counter.

    + +
  • +
  • Modified demos All.py and ScrolledText.py so that demos can be called + from directories other than the demos directory. (Case Roole and + Guido van Rossum)

    + +
  • +
  • Changed the default for the Pmw.Balloon label_justify option to + left to improve appearance of multi-line balloons. Pmw.Balloon + now replaces newlines with spaces in the statusHelp string so that + the strings look better when displayed in a Pmw.MessageBar. + (Andreas Kostyrka)

    + +
  • +
  • Pmw.Blt now calls package require BLT when checking for the + existence of Blt, so that it can be loaded if it is not statically + linked. (Clemens Hintze, Matthias Klose)

    + +
  • +
  • Copied earthris.gif and flagup.bmp files from Tcl distribution to + test directory, just in case they have not been installed. + (Jonathan Kelly)

    + +
  • +
  • Lots of improvements to the documentation and documenting recent + changes.

    + +
+

16 October 1997

+ +
  • Modified Pmw.Balloon and Pmw.ComboBox to work around a bug in the + Windows95 version of Tk which caused the popup windows to appear + in the wrong place. (Fredrik Lundh and Jerome Gay)

    + +
  • +
  • Added Pmw.maxfontwidth() function. (Rob Pearson)

    + +
+

24 October 1997

+ +
  • Changed PmwBase._reporterror to handle the class exceptions of + python 1.5. (Case Roole)

    + +
+

29 October 1997

+ +
  • Fixed a bug in forwardmethods() function which occurred if the + toClass class had a method called type.

    + +
+

7 November 1997

+ +
  • Changed tests/Test._getErrorValue to handle the class exceptions of + python 1.5. (Michael McLay)

    + +
  • +
  • Changed bug fix in forwardmethods() function to use the + exec execString in d construct. (Guido van Rossum)

    + +
  • +
  • Can now use Pmw.MegaArchetype as a base class just to get option + handling; it will not create the hull component unless requested. + Moved __str__() and interior() methods from Pmw.MegaToplevel and + Pmw.MegaWidget to Pmw.MegaArchetype class.

    + +
+

10 November 1997

+ +
  • Added textclass option to Pmw.ScrolledText and listboxclass + option for Pmw.ScrolledListBox to allow embedding of custom + widgets.

    + +
  • +
  • Added Mitch Chapman's FontText module to the demos directory + and used it to display the demo source code in color.

    + +
  • +
  • Added two notebook megawwidgets, Pmw.NoteBookR and Pmw.NoteBookS. + (Case Roole and Joe Saltiel)

    + +
  • +
  • Added Pmw.ScrolledCanvas megawidget. (Joe Saltiel)

    + +
  • +
  • Added Pmw.TreeBrowse megawidget. (Michael McLay)

    + +
  • +
  • Added Pmw.Group megawidget and modified to use grid() instead + of pack(). (Case Roole)

    + +
  • +
  • Release of version 0.5

    + +
+

12 November 1997

+ +
  • Added pyclass option to components and removed textclass + option from Pmw.ScrolledText and listboxclass option from + Pmw.ScrolledListBox. (Suggested by Shen Wang)

    + +
  • +
  • Added label component to Pmw.ButtonBox megawidget.

    + +
  • +
  • Fixed mis-spelling of PmwTreeBrowse in Pmw.py.

    + +
  • +
  • Release of version 0.5.1

    + +
+

5 December 1997

+ +
  • The pyclass option can now be None. If so, createcomponent + returns None.

    + +
  • +
  • Removed tagtype option from Pmw.Group. Can now use the more + general tag_pyclass instead.

    + +
  • +
  • Added tcl call to load {} Blt when testing for presence of Blt.

    + +
  • +
  • Added julian and papal options to Pmw.ymdtojulian and + Pmw.juliantoymd functions and made sure divisions give the same + result as C even when operands are negative.

    + +
  • +
  • Exported ymdtojulian and juliantoymd functions.

    + +
  • +
  • Fixed bug in activate method. Did not prepend TclError with Tkinter.

    + +
  • +
  • When the Blt busy hold command is called from showbusycursor, the + bindtags on the busy window are set so that no events cause + callbacks to occur for the toplevel or all bindings. Also, while + a busy window is up, the focus is changed to the busy window so + that no keyboard events are accepted. This fixes a bug where the + Tkinter._nametowidget function could crash with a KeyError: _Busy + if there was a binding on a toplevel window and the mouse + was pressed while the busy cursor was up.

    + +
+

9 December 1997

+ +
  • Fixed bug in Pmw.datestringtojdn() when dealing with century year, + such as 2000.

    + +
+

10 December 1997

+ +
  • Added where option to Pmw.ScrolledText.importfile(). (Graham + Matthews)

    + +
+

16 December 1997

+ +
  • Modified Pmw.RadioSelect and Pmw.ButtonBox so that you can no + longer index their buttons using regular expressions. This + feature seemed to have little use and caused problems with buttons + labeled for example a* and b*. (Problem reported by Rob + Hooft)

    + +
  • +
  • Added updateFunction option to Pmw.busycallback(). If set, the + function will be called just after the command given to + Pmw.busycallback(). If the function is set the Tkinter update() + method, then this will clear any events that may have occurred + while the command was executing.

    + +
+

30 December 1997

+ +
  • Changed ymdtojulian and juliantoymd functions to jdntoymd and + ymdtojdn, because the meaning of "julian" is ambiguous, whereas + the meaning of "Julian Day Number" is not (maybe).

    + +
  • +
  • Converted Pmw to use python 1.5 package mechanism. (Michael McLay + and Case Roole)

    + +
  • +
  • Removed Pmw.py and PmwLazy files. Added __init__.py, PmwLoader.py + and Pmw.def files. (Case Roole)

    + +
  • +
  • Applications can now specify at runtime which version of Pmw to + use and also which alpha versions, if any. (Case Roole)

    + +
  • +
  • Modified Pmw code for the version of Tkinter released with python + 1.5.

    + +
  • +
  • Release of version 0.6

    + +
+

5 January 1998

+ +
  • Fixed alpha version handling so that alpha versions do not have to + supply PmwBase.py and PmwUtils.py. (Case Roole)

    + +
  • +
  • Added example alpha directory and documentation. (Case Roole)

    + +
+

7 January 1998

+ +
  • Added selectmode option to Pmw.RadioSelect megawidget. (Roman + Sulzhyk)

    + +
  • +
  • Added some changes to Pmw.ScrolledCanvas to get around some bugs. + (Joe Saltiel)

    + +
  • +
  • Release of version 0.6.1

    + +
+

8 January 1998

+ +
  • Added some more changes to Pmw.ScrolledCanvas. (from Joe Saltiel)

    + +
+

12 January 1998

+ +
  • Added Pmw.OptionMenu megawidget. (Roman Sulzhyk)

    + +
+

20 February 1998

+ +
  • Added new Pmw.MenuBar features to delete menus and menuitems, + enable and disable menu bar and to add cascade menus. (Rob Pearson)

    + +
  • +
  • Added extra arguments to Pmw.Color.spectrum for more control over + color choice.

    + +
+

23 February 1998

+ +
  • Added canvasbind() method to Pmw.Balloon.

    + +
  • +
  • Fixed demos/All.py so that it will correctly determine which Pmw + version to use even if it is in a directory symlinked to the demos + directory.

    + +
  • +
  • Removed "import DemoVersion" from all demos, except All.py, so + that they will work unchanged when copied outside of the Pmw + distribution.

    + +
  • +
  • Release of version 0.6.2

    + +
+

26 February 1998

+ +
  • Fixed PmwLoader so that it works on Macintoshes. (Jack Jansen)

    + +
+

2 March 1998

+ +
  • Fixed PmwBase and PmwBlt so that an attempt is made to dynamically + load Blt before it is used. Previously only attempted to load Blt + when calling showbusycursor.

    + +
+

16 March 1998

+ +
  • Added hulldestroyed() method.

    + +
  • +
  • Modified displayerror() function to use value given to + reporterrorstofile() if it is set.

    + +
  • +
  • Fixed bug in Pmw.EntryField which occurred when the command + option destroyed the megawidget.

    + +
  • +
  • Pmw.EntryField invoke method now passes on the value returned by + the command function.

    + +
+

3 April 1998

+ +
  • Added Pmw.ScrolledFrame megawidget. (Joe Saltiel)

    + +
  • +
  • Color.rgb2hsi() now uses the built-in min() and max() functions.

    + +
+

20 April 1998

+ +
  • Moved time and date functions from PmwCounter.py to new file, + PmwTimeFuncs.py.

    + +
  • +
  • Added optional separator argument to timestringtoseconds and + datestringtojdn functions. These functions are now stricter + when checking if a string is a valid date or time. For example, + it now checks for correct day in month, month in year, etc. These + changes also affect the Pmw.Counter date and time validators.

    + +
  • +
  • The datestringtojdn function now accepts all combinations of + 'd', 'm', 'y' as format string.

    + +
  • +
  • Moved functions to bottom of file and class to top of file in + PmwEntryField.py and PmwCounter.py.

    + +
  • +
  • The validation for Pmw.EntryField integer, hexadecimal and + real types now use string.atol or string.atof rather than + regular expressions.

    + +
  • +
  • The validation for the Pmw.EntryField real type accepts a + separator argument, for those who prefer a comma instead of a + full stop/period/point as the decimal dividing symbol.

    + +
  • +
  • The Pmw.EntryField time* and date_* validators have been + removed. The functionality can be replaced by using the new + time and date validators with min and max fields.

    + +
  • +
  • The Pmw.EntryField maxwidth option has been removed. The + functionality can be replaced by using the max field of the + validator.

    + +
  • +
  • Added an extravalidators option to Pmw.EntryField. This allows + new types of validation to be added, particularly in classes + derived from Pmw.EntryField. It also allows the use of different + names for the same validation, by using aliases. Added + SpecialEntry demo to show extravalidators option, based on work + by Joachim Schmitz.

    + +
  • +
  • Fixed a bug in Pmw.EntryField when combining use of value and + entry_textvariable options.

    + +
  • +
  • The Pmw.EntryField validate option now also accepts a dictionary + to handle minimum and maximum validation and to allow the passing + of other arguments to the validating functions, such as date, time + and number formats and separators.

    + +
  • +
  • Fixed bug in Pmw.EntryField where the entry would scroll to the + start of the text if an invalid character was typed.

    + +
  • +
  • Added checkentry() method to Pmw.EntryField, so that it can be + updated if the entry widget is tied to a textvariable.

    + +
+

10 May 1998

+ +
  • The activate() method now takes a geometry option to allow more + flexible positioning of the modal dialog.

    + +
  • +
  • Fixed rarely occurring bug in deactivate() method if it is called + (perhaps from a timer) during the call to wait_visibility() in the + activate() method. This bug used to generate an error and the + application would not exit properly.

    + +
  • +
  • Fixed another rarely occurring bug in deactivate() method if it is + called while another application has the grab.

    + +
  • +
  • Removed "sys.exc_traceback = None" for except clauses which used + to be required by python 1.4 so that references to objects in the + stack trace would not be left.

    + +
  • +
  • Now uses sys.exc_info() function when displaying exception + traceback.

    + +
  • +
  • The state option of Pmw.Balloon and the orient option of + several others now generate an exception if they have a bad value.

    + +
  • +
  • Added a deactivatecommand option to Pmw.MegaToplevel which can be + used, for example, to cancel timers.

    + +
  • +
  • Made changes to Pmw.Counter so that the entry display continuously + changes when arrow key presses are repeated quickly.

    + +
  • +
  • Made changes to Pmw.Counter so that the insertion cursor is maintained + while counting and the entry scrolls to the end if the value is long.

    + +
  • +
  • Pmw.Counter now behaves correctly when counting past the maximum + and minimum values of the EntryField.

    + +
+

28 May 1998

+ +
  • Made all Pmw.EntryField standard validators publicly available + as Pmw.numericvalidator, etc.

    + +
  • +
  • Now uses faster string.replace() instead of regsub.gsub() when + applicable.

    + +
  • +
  • If the balloonHelp argument of the Pmw.Balloon bind methods is + None, no balloon is displayed.

    + +
  • +
  • Merged the code from the PmwUtils module (forwardmethods()) into + PmwBase, since it was always used, was used nowhere else, and made + freezing a little more complicated.

    + +
  • +
  • Added a short delay between calling Tkinter bell() method (sounds nicer).

    + +
  • +
  • The functions datestringtojdn() and timestringtoseconds() now + return ValueError on invalid input.

    + +
  • +
  • Created bundlepmw.py, to help when freezing in Pmw. Placed in bin + directory.

    + +
+

29 May 1998

+ +
  • Fixed rare bug in Pmw.Counter which occured if the counter was + unmapped while the mouse button was held down over an arrow button.

    + +
  • +
  • Created contrib directory and placed PmwVerticalGuage.py in it. + (Chris Wright)

    + +
  • +
  • Patched PmwNoteBookR.py. (Siggy Brentrup)

    + +
  • +
  • Added addoptions() method to Pmw.MegaArchetype class. (Dieter Maurer)

    + +
  • +
  • By default, MenuBar creates hotkeys for menus and menu items for + keyboard traversal. Added traversSpec argument to MenuBar add + methods. (Michael McLay)

    + +
+

31 May 1998

+ +
  • Cleaned up bbox() methods in Pmw.ScrolledCanvas and + Pmw.ScrolledListBox.

    + +
  • +
  • The createcomponent() method now disallows the creation of + component names containing an underscore, since the query + functions would not be able to find them.

    + +
+

2 June 1998

+ +
  • Release of version 0.7

    + +
+

3 June 1998

+ +
  • Moved Pmw.TreeBrowse megawidget to contrib directory.

    + +
+

17 June 1998

+ +
  • Added PmwFullTimeCounter.py to contrib directory (Daniel Michelson)

    + +
+

1 July 1998

+ +
  • Changed mispelt file PmwVerticalGuage.py to PmwVerticalGauge.py + in contrib directory.

    + +
+

7 July 1998

+ +
  • Fixed bug in Pmw.Counter real datatype. Sometimes incorrectly + counted negative decimal fractions. (Reported by David Ascher)

    + +
+

12 July 1998

+ +
  • The format argument of Pmw.datestringtojdn() now defaults to + 'ymd'.

    + +
  • +
  • Removed Tkinter_test.py from tests since it does not test any Pmw + functionality (only Tkinter) and it fails under MS-Windows 95.

    + +
+

23 August 1998

+ +
  • Changed several exception types to be more consistent.

    + +
  • +
  • Made the interface to Pmw.Blt.Vector more like the builtin python + list type.

    + +
  • +
  • It is no longer an error to call Pmw.setversion() or + Pmw.setalphaversions() after initialisation, as long as the + requested version matches the actual version.

    + +
  • +
  • Fixed Pmw.NoteBookR so that it behaves better when the + highlightthickness is changed.

    + +
  • +
  • The setyearpivot() function now returns a tuple containing the old + values of pivot and century.

    + +
  • +
  • Added PmwFileDialog.py to contrib directory (Rob Hooft)

    + +
  • +
  • Modified demos so that full tracebacks are displayed if an error + occurs when importing a module.

    + +
  • +
  • Removed justify() method from Pmw.ScrolledListBox, since it is + just a wrapper around the xview and yview methods of the listbox. + Also, it was not a permanent justification, as the name implied.

    + +
+

20 September 1998

+ +
  • Changed implementation of Pmw.ScrolledCanvas.

    + +
  • +
  • Added borderframe option to Pmw.ScrolledText and Pmw.ScrolledCanvas.

    + +
+

18 October 1998

+ +
  • Major overhaul of all scrolled widgets. Modified all to use + similar structure, given the peculiarities of each. Fixed several + subtle bugs.

    + +
  • +
  • Pmw.ScrolledFrame: now uses a frame positioned within a clipping + frame using the place geometry manager. Added borderframe, + horizflex, horizfraction, usehullsize, vertflex, vertfraction + options. Added reposition() method. Removed getFrame() method; + use interior() method instead.

    + +
  • +
  • Pmw.ScrolledListBox: added usehullsize option.

    + +
  • +
  • Pmw.ScrolledText: added borderframe and usehullsize options.

    + +
  • +
  • Pmw.ScrolledCanvas: simplified widget structure. Added + borderframe, canvasmargin, scrollmargin and usehullsize options. + Added label.

    + +
  • +
  • Modified Pmw.OptionMenu to use standard widgets rather than call + tcl procedure. Added initialitem option. Now handles + menubutton_textvariable component option correctly.

    + +
+

1 November 1998

+ +
  • Documented more Pmw functions and Pmw.ComboBox.

    + +
+

15 November 1998

+ +
  • Fixed some bugs, cleaned up code and wrote documentation for + Pmw.Group. Removed ringpadx and ringpady options, since this + functionality is more generally available by padding the + megawidget itself and by padding the children of the megawidget. + Modified Pmw.aligngrouptags so that it takes into account the + borderwidth and highlightthickness of the ring and so that it + works when there is no tag widget. Added tagindent option.

    + +
+

18 November 1998

+ +
  • Renamed canvasbind() and canvasunbind() methods of Pmw.Balloon to + tagbind() and tagunbind() and modified so that they work with both + Tkinter.Canvas items and Tkinter.Text tagged items.

    + +
+

19 November 1998

+ +
  • Added havebltbusy() method to Pmw.Blt. (Robin Becker)

    + +
+

21 November 1998

+ +
  • Modified contrib/PmwFileDialog.py so that when a file is selected + with the mouse, the highlight (in the file list) persists and the + file list does not scroll to the top. (Rob Hooft)

    + +
  • +
  • Modified Pmw.Balloon so that it can be bound to a tag associated + with several Canvas or Text items. (Magnus Kessler)

    + +
+

21 November 1998

+ +
  • Cleaned up appearance and colors of Pmw.NoteBookR tabs. (Georg + Mischler)

    + +
  • +
  • Added buttontype option to Pmw.RadioSelect to support + radiobuttons and checkbuttons. (Georg Mischler)

    + +
+

23 November 1998

+ +
  • Updated usage of bind_class(tag) due to change in return value + in Tkinter module in python 1.5.2. (Magnus Kessler, Fredrik Lundh)

    + +
  • +
  • The default time displayed in Pmw.TimeCounter is now the current + local time, not GMT as before.

    + +
  • +
  • The times displayed in the Counter demonstration are now the + current local time, not GMT as before.

    + +
+

7 December 1998

+ +
  • Modified Pmw.ComboBox to take advantage of the fix to the Tkinter + bind() method callback handling of Event.widget in python + 1.5.2. It works even if the selectioncommand destroys the + combobox. For simple comboboxes, the invoke() method now returns + the return value of the selectioncommand.

    + +
  • +
  • Modified Pmw.EntryField to take advantage of the fix to the + Tkinter bind() method callback handling of Event.widget in + python 1.5.2. It works even if a user-supplied callback + (command, invalidcommand, validator or stringtovalue) + destroys the entryfield. Cleans up correctly when destroyed. The + invoke() method now returns the return value of the command.

    + +
  • +
  • The invoke() method of Pmw.TimeCounter now returns the return + value of the command.

    + +
  • +
  • Modified Pmw.ButtonBox to use the new (in Tk8.0) default option + of the Tkinter Button widget instead of a separate frame. + Changed default padding to be more compact. Removed "ring" frame + component and "ringborderwidth", "ringpadx" and "ringpady" + options. (Georg Mischler)

    + +
  • +
  • Changed 'pmw1' fontScheme to set default fonts only when running + under posix, since the default fonts on other systems look better.

    + +
+

10 December 1998

+ +
  • Release of version 0.8

    + +
+

20 January 1999

+ +
  • Added master option to Pmw.MegaToplevel and removed master + argument from the activate method.

    + +
  • +
  • Replaced rand module in demos with a simple random number + generator (since rand is not built-in on all versions of python).

    + +
+

22 February 1999

+ +
  • Modified __init__.py so that it only accepts directories whose + names begin with Pmw_M_N and which have a /lib/PmwLoader.py/ + file.

    + +
+

13 May 1999

+ +
  • Changed Pmw.ScrolledCanvas, Pmw.ScrolledText and Pmw.ScrolledListBox + to speed up scrolling if the scrollmodes are not both dynamic.

    + +
  • +
  • Changed busy cursor and activate/deactivate code so that it works + correctly under fast mouse clicking or fast keyboarding (using + accelerators). Also fixed so that grab is correctly restored + after a Pmw.ComboBox popup list is unmapped inside a modal dialog. + (Clemens Hintze)

    + +
  • +
  • Several dialogs now give focus to one of their components (listbox + or entry widget) when activated. (Clemens Hintze)

    + +
  • +
  • Fixed Pmw.ComboBox so that it unposts popup if the combobox is + unmapped and returns grab and focus correctly if destroyed.

    + +
  • +
  • Improved tracetk() output to be more readable. Also displays + nested calls to the Tk mainloop better and shows callbacks from + tcl to python.

    + +
  • +
  • Upgraded Blt support to blt2.4i. Graph widget is not backwards + compatible with blt2.1.

    + +
+

19 May 1999

+ +
  • Fixed bug in Pmw.Balloon in placement of balloons over canvas + items when the canvas was scrolled. (Tessa Lau)

    + +
+

20 May 1999

+ +
  • Added new Tk event types (new in Tk 8.0 and 8.0.5) to PmwBase + error display method. Also added check for unknown event types to + safeguard against future changes. (Magnus Kessler)

    + +
  • +
  • Added exclude argument to showbusycursor(). (Rob Hooft)

    + +
+

1 June 1999

+ +
  • Added wrappers for Blt Stripchart and Tabset widgets. (Nick Belshaw)

    + +
  • +
  • Changed createcomponent() so that arguments to the constructor of + the component can now be specified as either multiple trailing + arguments to createcomponent() or as a single tuple argument.

    + +
+

7 June 1999

+ +
  • Added call to update_idletasks() in Pmw.ScrolledCanvas, + Pmw.ScrolledFrame, Pmw.ScrolledText and Pmw.ScrolledListBox to + avoid endless mapping/unmapping of two dynamic scrollbars when the + window is first mapped and only one scrollbar is needed. + (Reported by Mark C Favas, solution suggested by Dieter Maurer.)

    + +
+

10 June 1999

+ +
  • Fixed bug in bundlepmw.py when called with -noblt option. + (Reported by Kevin O'Connor)

    + +
  • +
  • Pmw.ComboBox now unposts the dropdown listbox before the selection + callback is invoked, to avoid problems when the callback takes a + long time to run. (Reported by Randall Hopper)

    + +
+

11 June 1999

+ +
  • Release of version 0.8.1

    + +
+

29 June 1999

+ +
  • PmwMessageBar.message() now replaces newlines with spaces before + displaying message. Also applies to helpmessage().

    + +
+

2 July 1999

+ +
  • Improved toplevel window positioning under NT, and stopped most of + the ugly flashing.

    + +
+

5 July 1999

+ +
  • The pmw1 fontScheme is now supported under NT, as is the size + option to Pmw.initialise().

    + +
+

6 July 1999

+ +
  • Changed the names of positional arguments in the following + methods, so that they have less chance of conflicting with keyword + arguments: MegaArchetype.createcomponent(), ButtonBox.insert(), + ButtonBox.add(), MenuBar.addcascademenu(), MenuBar.addmenuitem() + and RadioSelect.add().

    + +
+

9 July 1999

+ +
  • Added images and example code to the megawidget reference manuals. + (Suggested by Joerg Henrichs)

    + +
  • +
  • Fixed showbusycursor() under NT. It now calls update() instead of + update_idletasks() to force display of cursor. (Solution + suggested by George Howlett)

    + +
  • +
  • Improved display of arrows in ComboBox, Counter and TimeCounter.

    + +
+

16 July 1999

+ +
  • Removed Pmw.maxfontwidth() function, since better functionality is + now supplied by the Tk "font measure" command.

    + +
  • +
  • Removed Pmw.fontexists() function, since in Tk8.0 all fonts exist.

    + +
+

28 July 1999

+ +
  • Fixed bug in date counter with separator other than '/' and time + counter with separator other than ':'. (David M. Cooke, Alan + Robinson)

    + +
  • +
  • Under NT, the font named 'fixed' is not fixed width, so added + alias from 'Fixed' to 'Courier'.

    + +
  • +
  • Changed the bind() and tagbind() methods of Pmw.Balloon to + remove a potential memory leak. The methods now store the + funcids of the callback functions, so that if the same widget or + tag is bound twice, the balloon can remove the old bindings. + (Peter Stoehr)

    + +
  • +
  • Changed NoteBookR so that lowercmd, creatcmd and raisecmd are + called in that order when a page is selected. Also fixed bug + which always raised page 0 when notebook is resized. (Scott + Evans, Charles Choi)

    + +
+

1 August 1999

+ +
  • Added dynamicGroups argument to defineoptions() method and + modified ButtonBox, MenuBar, PanedWidget, RadioSelect to register + their dynamic groups.

    + +
  • +
  • Pmw.initialise() can now be called multiple times, with + different root arguments, but only sequentially. Pmw does not + (yet) support multiple simultaneous interpreters. Modified + Pmw.EntryField so that it recreates class bindings when + Tkinter.root changes.

    + +
+

4 August 1999

+ +
  • Added relmouse option to Pmw.Balloon. Fixed Pmw.Balloon so that + the balloon is not displayed off-screen. (Tessa Lau)

    + +
+

16 August 1999

+ +
  • Added disableKeyboardWhileBusy option to initialise(). To ignore + keyboard input while displaying the busy cursor, Pmw sets the + focus for each toplevel window to the Blt busy window. However, + under NT, this causes each window to be raised. If this is not + acceptable, programs running on NT can request show/hidebusycursor + not to ignore keyboard input.

    + +
+

25 August 1999

+ +
  • Added Pmw.Blt.busy_forget() and used it in Pmw.hidebusycursor() + when running under NT. There is a bug in the Blt busy release + command under NT where it sometimes fails to display the busy + cursor. Using busy forget avoids the problem.

    + +
+

27 September 1999

+ +
  • Added busyCursorName option to Pmw.initialise() and added cursor + argument to Pmw.Blt.busy_hold(). (Mark Favas)

    + +
+

20 October 1999

+ +
  • Replaced Pmw.NoteBookR and Pmw.NoteBookS with completely rewritten + Pmw.NoteBook.

    + +
  • +
  • Renamed Pmw.OptionMenu.get() to Pmw.OptionMenu.getcurselection() + and Pmw.PanedWidget.remove() to Pmw.PanedWidget.delete(), to be + more consistent with other megawidgets.

    + +
  • +
  • The index() method of several megawidgets now use Pmw.END, + Pmw.SELECT and Pmw.DEFAULT instead of strings, since these may + conflict with component names.

    + +
  • +
  • Pmw.OptionMenu.index() now uses Pmw.SELECT to return + index of the currently selected menu item, rather than None.

    + +
  • +
  • Added destroy() method to Pmw.MegaArchetype to handle cleaning up + of _hullToMegaWidget mapping.

    + +
  • +
  • Removed exclude argument from Pmw.showbusycursor() and added + Pmw.excludefrombusycursor() function instead. (Rob Hooft)

    + +
  • +
  • Fixed several bugs for Windows NT.

    + +
  • +
  • Added Pmw.ButtonBox.button() and Pmw.RadioSelect.button().

    + +
  • +
  • Added Pmw.Color.bordercolors().

    + +
+

21 October 1999

+ +
  • Release of version 0.8.3. (Version 0.8.2 was not released.)

    + +
+

30 October 1999

+ +
  • Added arrownavigation option and previouspage() and nextpage() + methods to Pmw.NoteBook. (Peter Funk)

    + +
  • +
  • Renamed the setnaturalpagesize() method of Pmw.NoteBook to + setnaturalsize() to be consistent with Pmw.PanedWidget.

    + +
  • +
  • Changed Pmw.excludefrombusycursor() to Pmw.setbusycursorattributes(). + Removed busyCursorName option from Pmw.initialise() and added + cursorName attribute to Pmw.setbusycursorattributes().

    + +
  • +
  • Added documentation source and build scripts to ftp site.

    + +
+

6 November 1999

+ +
  • Fixed memory leaks when destroying megawidgets. Added automatic + check for memory leak to test script used by all tests. + Pmw.initialise() now uses a hook into Tkinter.Widget.destroy + rather than Tkinter.Frame.destroy to handle the case of + Pmw.NoteBook being destroyed (since the notebook hull is a canvas + and not a frame). Window manager delete protocol callbacks are + now cleaned up. Pmw.ScrolledListBox event bindings now do not + leak. (Reported by Jeff Weeks)

    + +
  • +
  • Removed key bindings for Pmw.ScrolledListBox except space and return keys.

    + +
+

20 November 1999

+ +
  • Fixed bug in Pmw.Balloon when the canvas or text item that + triggered the balloon is deleted before the balloon is displayed + by the initwait timer. (Magnus Kessler)

    + +
  • +
  • Added 'nograb' to globalMode option of activate() method. (Rob Hooft)

    + +
  • +
  • Added __setitem__ method to Pmw.MegaArchetype, so that megawidget + options can be now set using megawidget['option'] = value style. + (Oliver Gathmann)

    + +
+

27 December 1999

+ +
  • Converted from regex module to re module, since regex is not + implemented for Jpython. (Finn Bock)

    + +
+

30 December 1999

+ +
  • Added clear() method to Pmw.ScrolledListBox (suggested by Carson + Fenimore).

    + +
+

15 March 2000

+ +
  • Fixed problem in PmwBase when deleting windows that were created + before Pmw was initialised (such as splash windows displayed while + the application is coming up). (Mark Favas)

    + +
  • +
  • Added splash window to Pmw demo. (Mark Favas)

    + +
+

30 April 2000

+ +
  • Added Pmw.MainMenuBar megawidget, which uses the menubar feature + of Tk to provide platform specific menu bars.

    + +
  • +
  • Fixed Pmw.Counter and several other megawidgets so that certain + hull constructor keywords, such as hull_relief and + hull_borderwidth, are not overriden in the constructor.

    + +
  • +
  • Thanks to Peter Cashin for his help on how to unpack gzipped tar + files on Microsoft Windows operating systems.

    + +
  • +
  • Added Pmw.HistoryText megawidget. This can be used as the basis + of an interactive text-based database query gui. It maintains a + history of each query and allows editing of prior queries.

    + +
  • +
  • Added references to the Pmw.Blt.Graph documentation by Bjørn Ove + Thue and Hans Petter Langtangen.

    + +
  • +
  • Searched for and fixed memory leaks. There are no more known memory leaks.

    +
    • For commands created by bind: these are cleaned up by Tkinter + when the widget is destroyed. Pmw.Balloon, which repeatedly + binds to the same widget (or item, using tag_bind), has been + fixed by passing the old command into the call to unbind or + tag_unbind which is cleaned up by Tkinter.

      + +
    • +
    • For commands created by class_bind: most class bindings are + only created once (per Tk interpreter) and so do not need to be + cleaned up. The exception is adding and deleting menus in + Pmw.MenuBar. This has now been fixed to clean up class_bind + commands when deleting menus.

      + +
    • +
    • Callbacks given to command, xscrollcommand, yscrollcommand, etc + options are cleaned up by Tkinter when the widget is destroyed. + Cases where Pmw repeatedly sets such options have now been fixed + to clean up the old command before configuring the new one. + These are in setitems in Pmw.OptionMenu and when modifying the + scrollcommand options in several of the scrolled widgets.

      + +
    • +
    • Pmw now cleans up calbacks it registers with the + WM_DELETE_WINDOW protocol for toplevel windows.

      + +
    + +
  • +
  • Added ManualTests.py to tests directory for tests which need to be + run by hand.

    + +
+

12 May 2000

+ +
  • Release of version 0.8.4.

    + +
+

17 May 2000

+ +
  • Modified Pmw.Counter to deal with the presence (python up to + 1.5.2) or absence (python 1.6 and after) of an L at the end of + the ascii representation of a long. (Mark Favas)

    + +
  • +
  • Fixed bug in Pmw.ScrolledFrame when given invalid flex options. + (Stephen D Evans)

    + +
+

23 January 2001

+ +
  • Moved Pmw home from www.dscpl.com.au to pmw.sourceforge.net.

    + +
  • +
  • Added pmw2 font scheme, since the font used for balloon text with + pmw1 is too small on Linux.

    + +
  • +
  • Removed syntax coloring from code window in demos. It did not + look good and the pattern matching was not always correct.

    + +
  • +
  • Changed font size used for demos to 12 for Unix, since 14 looked + too big under Linux.

    + +
  • +
  • Minor fixes to tests for Tk 8.3.

    + +
+

8 February 2001

+ +
  • Release of version 0.8.5

    + +
+

18 February 2001

+ +
  • Added xview() and yview() methods to Pmw.ScrolledFrame (suggested + by Christer Fernstrom).

    + +
  • +
  • Made tktrace output more readable.

    + +
  • +
  • Added noBltBusy option to Pmw.initialise.

    + +
  • +
  • Fixed bug where combobox dropdown list could stay mapped after + entryfield was unmapped.

    + +
  • +
  • Improved scrolling in scrolled frame.

    + +
+

21 February 2001

+ +
  • Fixed tests for recent version of Blt graph (reported by + Venkatesh Prasad Ranganath).

    + +
  • +
  • Fixed problem in Pmw.ScrolledFrame in python 1.5 - string.atof + does not accept a number as argument, but it does in python 2.0.

    + +
+

24 February 2001

+ +
  • Modified Pmw.OptionMenu documentation to specify that list + elements must be strings (problem reported by Guy Middleton).

    + +
  • +
  • Fixed bug in Pmw.OptionMenu where the wrong item was displayed + when an integer item in the menu was selected with the mouse (even + though items should be strings).

    + +
  • +
  • Added work around to Pmw.ScrolledFrame for bug in Tk when + retrieving value from scrollbars soon after creation.

    + +
+

27 February 2001

+ +
  • Added HistoryText and MainMenuBar to bin/bundlepmw.py - accidently + left out.

    + +
+

13 April 2001

+ +
  • Changed default foreground (text) of Pmw.Balloown to black. (Eric + Pettersen)

    + +
  • +
  • Added default fontScheme to Pmw.initialise().

    + +
  • +
  • Added -fontscheme and -fontsize options to demo.

    + +
  • +
  • Added updatelayout() to Pmw.PanedWidget for use when dynamically + adding and deleting panes. (G Cash)

    + +
  • +
  • Added move() to Pmw.PanedWidget to move panes. (G Cash)

    + +
+

20 April 2001

+ +
  • Fixed bug in Pmw.Balloon where the balloon would reappear if the + mouse button was pressed down inside a widget and then, while the + mouse button was being held down, the mouse was moved outside of + the widget and then moved back over the widget.

    + +
  • +
  • Fixed bug in Pmw.Balloon when destroying widgets while the balloon + was up. In this case, the balloon remained displayed even though + the widget had been destroyed. (Reported by Stefan Schone.)

    + +
  • +
  • Fixed bug in Pmw.Balloon when destroying widgets during the + initwait period. In this case, an error occurred when the + initwait timer went off when it tried to access the destroyed + widget. (Reported by Stefan Schone.)

    + +
  • +
  • Fixed Pmw.Balloon so that unbinding withdraws the balloon if + the widget being unbound is the widget which triggered the balloon.

    + +
  • +
  • Modified Pmw.Balloon so that when deleting a canvas or text item, + tagunbind() can be called which will withdraw the balloon if it + was triggered by the item. Unfortunately this can not be + automated as for widgets since Tk does not support <Destroy> + bindings on canvas or text items, so there is no way that + Pmw.Balloon can be notified of the deletion of an item.

    + +
  • +
  • Updated tests for python 2.1.

    + +
+

21 May 2001

+ +
  • Pmw.OptionMenu now defaults to taking focus (on <Tab> key).

    + +
+

15 May 2002

+ +
  • Fixed bug in Pmw.Graph.element_closest() where element names + should follow option arguments. (Val Shkolnikov)

    + +
+

5 June 2002

+ +
  • Added command option to Pmw.TimeCounter.

    + +
  • +
  • Finished all documentation.

    + +
  • +
  • Fixed bug in documentation creation script which, since python + 2.0, printed default values of real options (such as the + horizfraction option of Pmw.ScrolledFrame) with too many digits + (such as 0.050000000000000003).

    + +
  • +
  • Fixed bug in setgeometryanddeiconify for cygwin python (John + Williams).

    + +
+

4 July 2002

+ +
  • Added master option to MegaToplevel.show()

    + +
  • +
  • Improved MegaToplevel.show() so that tkraise is not called + unecessarily, thus avoiding 2 second delay under certain window + managers (such as sawfish) in most circumstances. There are still + problems with the Enlightenment window manager.

    + +
+

18 August 2002

+ +
  • Added columnheader, rowheader and rowcolumnheader components to + Pmw.ScrolledText. (Rob Pearson)

    + +
  • +
  • Added getvalue() and setvalue() methods to several megawidgets + as a consistent way to set and get the user-modifiable state. + (Cimarron Taylor)

    + +
  • +
  • Made sub-classing simpler when no new options or components are + being created. A sub-class of a Pmw megawidget does not need to + have an __init__() method. If it does, it does not need to call + defineoptions(). Also, initialiseoptions() no longer requires an + argument (for backwards compatibility it may take an argument, but + it is ignored).

    + +
+

24 August 2002

+ +
  • Release of version 1.0

    + +
+

26 August 2002

+ +
  • Minor fixes.

    + +
  • +
  • Release of version 1.1

    + +
+

4 September 2002

+ +
  • Added collapse, expand and toggle methods and collapsedsize option + to Pmw.Group. (Rob Pearson)

    + +
+

5 September 2002

+ +
  • Added sticky option to several megawidgets.

    + +
+

18 September 2002

+ +
  • Added appendtext method to Pmw.ScrolledText. (Graham Dumpleton)

    + +
+

26 September 2002

+ +
  • Modified Pmw.ScrolledListBox to call dblclickcommand on + <Double-ButtonRelease-1> rather than <Double-ButtonPress-1> which + caused problems if the double button press unmapped the + ScrolledListBox. In this case, the second button release of the + double click is given to another widget. (Eric Pettersen)

    + +
+

14 June 2003

+ +
  • Changes for python 2.3 and Tcl/Tk 8.4.2:

    +
    • Wrapped calls to cget() for Tkinter widgets in a call to + str(). Before python 2.3 cget() always returned a string. + Under python 2.3, Tkinter sometimes returns non-string values + (such as int, or Tcl_Obj). Made similar change when using + configure() to retrieve values. Fixed tests to handle integer + and Tcl_Obj return value from cget(). (Charles Doutriaux)

      + +
    • +
    • Fixed uses of col field of grid command. Must use full + column under Tcl/Tk 8.4.2.

      + +
    • +
    • Fixed PmwEntryField.py, PmwMessageBar.py, PmwScrolledField.py + so that the text is not greyed out under Tcl/Tk 8.4.2. This + was caused by a change in behaviour of the 'disabled' state + and the Tk entry widget. Now use new 'readonly' state for + Tcl/Tk 8.4.2.

      + +
    • +
    • Test script now ignores Blt test for Tcl/Tk 8.4.2, since it + causes Blt 2.4z to core dump. Blt needs to be fixed.

      + +
    • +
    • Changed Dialog test to work around problem caused by Tk 8.4.2 + enforcing transient behaviour of windows. When activate() is + called on a dialog whose parent is withdrawn, then the dialog + window is made transient. Under old versions of Tk, the + transient dialog was displayed, but under 8.4.2 the dialog is + not displayed. Work around is to deiconify parent of dialog.

      + +
    + +
+

5 August 2003

+ +
  • Release of version 1.2

    + +
+

+ + + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/copyright.html b/Pmw/Pmw_1_2/doc/copyright.html new file mode 100644 index 00000000..0f5e7e8a --- /dev/null +++ b/Pmw/Pmw_1_2/doc/copyright.html @@ -0,0 +1,57 @@ + + + + + + Pmw copyright + + + + +

Pmw copyright

+ +

+ Copyright 1997-1999 Telstra Corporation Limited, Australia + Copyright 2000-2002 Really Good Software Pty Ltd, Australia

+ +

Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions:

+ +

The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software.

+ +

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +

+ + + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/counter1.gif b/Pmw/Pmw_1_2/doc/counter1.gif new file mode 100644 index 00000000..64efe355 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/counter1.gif differ diff --git a/Pmw/Pmw_1_2/doc/counter2.gif b/Pmw/Pmw_1_2/doc/counter2.gif new file mode 100644 index 00000000..be894ed3 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/counter2.gif differ diff --git a/Pmw/Pmw_1_2/doc/demosandtests.html b/Pmw/Pmw_1_2/doc/demosandtests.html new file mode 100644 index 00000000..d7190a3e --- /dev/null +++ b/Pmw/Pmw_1_2/doc/demosandtests.html @@ -0,0 +1,364 @@ + + + + + + Pmw demonstrations and tests + + + + +

Pmw demonstrations and tests

+ +

+ +

+ +

+ Pmw comes with an extensive range of demonstrations and tests. The + demonstrations can be used to get a feel for what is provided by Pmw + and the demonstration code can be viewed to see examples of how to + use Pmw. The tests can be executed to check that there are no + problems with running Pmw in your environment. + +

+ +
+

Demonstrations

+

+ The Pmw demos directory contains demonstration scripts + showing many of the features of Pmw megawidgets. To view a + comprehensive package of all the demonstrations, including a view of + the source code, run the All.py script. Run + All.py -help for a short description of the script's + options. + +

+ All of the demonstrations may also be run separately. Most of the + demonstrations show some of the features of one of the Pmw + megawidgets. For example, to see a demonstration of the ButtonBox + megawidget, change into the demos directory and + run + +

+
+
+
+python ButtonBox.py
+
+
+
+ +

+ Other demonstrations, which show other features of Pmw include +

+
+
+
+BltGraph.py         demonstrates the Pmw interface to
+                    the BLT graph and vector commands
+BltTabset.py        demonstrates the Pmw interface to
+                    the BLT tabset command
+Colors.py           how to set color schemes
+ConfigClass.py      how to configure the python class
+                    of a megawidger component
+ErrorHandling.py    how Pmw displays run time errors
+                    in a window
+ExampleDemo.py      template for new demonstrations
+Grid.py             the Tkinter Grid geometry manager
+LogicalFont.py      how to use standard values for fonts
+MessageInfo.py      how to extend the Pmw MegaToplevel
+                    class
+NestedDialogs.py    how nested modal dialogs behave
+Resources.py        how to use the option database to
+                    modify Tk widget option defaults
+Resources_Pmw.py    how to use the option database to
+                    modify megawidget option defaults
+ShowBusy.py         demonstrates the Pmw interface to
+                    the BLT busy command
+SpecialEntry.py     deriving from Pmw.EntryField
+Spectrum.py         some of the Pmw color handling
+                    functions
+SpeedTest.py        tests the speed of creating Pmw
+                    megawidgets
+TextDisplay.py      how to extend the Pmw MegaWidget
+                    class
+WidgetDestroy.py    megawidget destruction
+
+
+
+ +Creating demonstrations of new megawidgets +
+

+If you create a new megawidget you can create a demonstration for it +by using the file +ExampleDemo.py as a +template. This template allows the demonstration to be run +individually or to be automatically included as part of the +demonstration package All.py. You should take a copy of +the template and name the new file after your megawidget. You should +then replace each instance of the word EXAMPLE with the +name of your megawidget and replace the code in the +__init__ method with code to create and initialise one or +more instances of your megawidget, which should be a child of +parent. You can add other methods as necessary. + +

+ +
+

Tests

+

+ The Pmw tests directory contains a test framework + and a set of test scripts for Pmw. + The tests cover the standard Tkinter module and most of the Pmw megawidgets. + The tests make a great + demonstration of the flexibility of the megawidgets. Simply change + into the tests directory and run + python All.py. + +

+ If all tests pass there should be no output printed to standard + output. If any of the tests fail, please send the test output to + the maintainer at + gregm@iname.com. + +

+ +

+ All of the tests may be run separately. Most of the tests test the + features of one of the Pmw megawidgets. For example, to execute the + test for the ButtonBox megawidget, run + +

+ +
+
+
+python ButtonBox_test.py
+
+
+
+ +

+ The Test.py file contains general testing functions and is imported + by all test files. + Other files, which test other features of Pmw include +

+
+
+
+Blt_test.py           BLT vector and graph interface
+Colors_test.py        setting color schemes
+MegaWidget_test.py    creation of megawidget classes
+Options_test.py       option and component handling
+PmwBase_test.py       more option and component handling
+Tkinter_test.py       Tk widgets in the Tkinter module
+
+
+
+ +Creating tests for new megawidgets +
+

+If you create a new megawidget you should create a test for it. There +is no template file for creating tests, but by looking at the other +Pmw tests (for example, +ScrolledText_test.py) you +will get some idea of how to create a test for your megawidget. + +

+ +

+The test files are designed to be run both individually or +automatically by the test package All.py. Each test file +must define the testData tuple. This consists of a +sequence of 2-element tuples, each tuple being a test specification +for one megawidget. Usually a file tests only one megawidget and so +there is only one test specification. The first element in the +specification is the megawidget class and the second is a sequence of +(yet more) 2-element tuples. In each of these tuples, the first +element is a sequence of individual tests to perform on an instance of +the megawidget and the second element is a dictionary to use for +the keyword arguments when creating the instance. Each individual +test is a tuple, the meaning of which depends on the type of the first +element, which may be either a string, a function or a method of the +megawidget class, as explained below. + +

+ +
    +
  • +

    +If the first element is a string, then it is treated as an option of +the megawidget and configure() is called to set the option to the +value specified by the second element. After setting the option, +cget() is called to query the option. If the test tuple has three +elements, then the value returned by cget() must equal the value +specified by the third element. Otherwise, the value returned must +equal the value specified by the second element. For example, + +

    +
    +
    +
    +('vscrollmode', 'static'),
    +('text_relief', 'sunken'),
    +('vscrollmode', 'bogus', 'ValueError: bad vscrollmode ' +
    +  'option "bogus": should be static, dynamic, or none'),
    +
    +
    +
    + +
  • +
  • +

    +If the first element is a function or method, then the function or +method is called. The arguments to the call are given by the second +element. (As a special case, if the second element is not a tuple, it +is used as the only argument to the call.) The test tuple may have 2, +3 or 4 elements. + +

    +
      +
    • +

      +If it has two elements, then the value returned by the call must be +None. For example, + +

      +
      +
      +
      +(c.exportfile, '/tmp/ScrolledText_test.py'),
      +(os.unlink, '/tmp/ScrolledText_test.py'),
      +
      +
      +
      + +
    • +
    • +

      +If it has four elements, then the third element is a dictionary to use +for the keyword arguments in the call and the value returned by the +call must equal the value specified by the fourth element. For +example, + +

      +
      +
      +
      +(c.search, ('abc', '0.0'), {'nocase': 1}, '2.24'),
      +
      +
      +
      + +
    • +
    • +

      +If is has three elements and the third element is a dictionary, then +it is used for the keyword arguments in the call and the value +returned by the call must be None. For example + +

      +
      +
      +
      +(c.configurepane, 'first', {'size' : 200}),
      +
      +
      +
      + +
    • +
    • +

      +If is has three elements and the third element is not a dictionary, +then the value returned by the call must equal the value specified by +the third element. For example, + +

      +
      +
      +
      +(c.components, (), ['hull', 'label']),
      +(c.add, ('Legumes',),
      +  'ValueError: name "Legumes" already exists'),
      +
      +
      +
      + +
    • +
    +
  • +
+ +

+Some special functions and values supplied by the Test module that may +be used in the tests include: +

+
+
+
+Test.callback       callback taking no arguments
+Test.callback1      callback taking one argument
+Test.callbackN      callback taking any number of arguments
+
+Test.currentWidget  returns the widget instance being tested
+Test.num_options    returns number of options for the widget
+
+Test.earthris       a sample Tkinter.PhotoImage
+Test.flagup         a sample Tkinter.BitmapImage
+Test.floatvar       a Tkinter.DoubleVar
+Test.stringvar      a Tkinter.StringVar
+
+
+
+ +

+ To slow down a test (to see what is being displayed), add the + following line which sets the delay between tests to (say) 1000 + milliseconds: + +

+
+
+
+Test.setdelay(1000)
+
+
+
+ +

+ To print information about what is being tested, add the line: + +

+
+
+
+Test.setverbose(1)
+
+
+
+ +
+
+ + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/dynamicloader.html b/Pmw/Pmw_1_2/doc/dynamicloader.html new file mode 100644 index 00000000..01d701c3 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/dynamicloader.html @@ -0,0 +1,147 @@ + + + + + + Dynamic loader + + + + +

Dynamic loader

+ +

+ There are two aspects of Pmw, unrelated to megawidgets, that + require special attention. Firstly, Pmw is made up of many + sub-modules, potentially making access to its various classes and + functions cumbersome for the user. Secondly, Pmw is regularly + being modified and added to, thus requiring the release of new + versions. Therefore, techniques for making access to the + sub-modules easy and efficient and for dealing with the different + versions have been developed. These techniques are incorporated + into the dynamic loader which Pmw creates when it is first + imported.

+ +

The first purpose of the loader is to give access to all Pmw classes + and functions through a single entry point, the Pmw. prefix. For + example, to access the ComboBox class (which resides in one of the + sub-modules of Pmw), you just have to use Pmw.ComboBox. Without + the loader, this would be a more complicated reference, such as, + hypothetically, Pmw.PmwComboBox.ComboBox.

+ +

The second purpose of the loader is to delay the importing of the + sub-modules until they are needed. This improves the startup time + of applications which only use a few Pmw megawidgets. It also + allows more megawidgets to be added to the library without slowing + down applications which do not use them.

+ +

The third purpose of the loader is to allow a script using Pmw to + specify which version of Pmw it requires. This allows an + application to continue working correctly even after newer releases + of Pmw have been made which are not compatible with the version + expected by the application. Several versions of Pmw can be + installed at once, with the actual version used being specified by + each application. In addition, the loader can be configured to + search in one or more alpha versions of Pmw. These versions may + contain new megawidgets, or new versions of existing megawidgets, + that are currently not in the base releases.

+ +

Several functions are available to set and query the version of + Pmw being used. These are Pmw.setversion() and + Pmw.setalphaversions() which specify the version and alpha + versions (if any) to use for this session; Pmw.version() which + returns the version(s) being used by this session; and + Pmw.installedversions() which returns the version(s) of Pmw + currently installed. These are described in the + Pmw functions reference manual.

+ +

When Pmw is first imported, an instance of PmwLoader is created + and placed into sys.modules['Pmw']. From that point on, any + reference to attributes of the Pmw 'module' is handled by the + loader. The real Pmw package is stored in sys.modules['_Pmw'].

+ +

The loader searches the Pmw package base directory for + sub-directories with the prefixes Pmw_ and Alpha_, which + contain Pmw base releases and alpha releases. The version numbers + are given by the part of the directory name following the prefix. + These versions are available for use and are those returned by the + Pmw.installedversions function. The initial version is set to + the base release with the greatest version number. When the first + reference to a Pmw class or function is made, the loader reads the + files named Pmw.def in the current base version directory and + also in the alpha directories (if any). These files list all the + classes and functions supported by the version. Pmw attributes + are first searched for in the alpha directories and then in the + base version directory. The first directory which supports the + reference is used. In this way, alpha versions override base + versions.

+ +

The directory Alpha_99_9_example contains a simple example of + how to structure an alpha version. The following code can be used + to request that the alpha version be used and then creates an + instance of a new megawidget defined in the alpha version.

+ +
 import Pmw
+ Pmw.setalphaversions('99.9.example')
+
+ # Create a standard message dialog using the base Pmw version.
+ ordinary = Pmw.MessageDialog(
+     message_text = 'Ordinary\nPmw Dialog')
+
+ # Create an example dialog using the alpha Pmw version.
+ alpha = Pmw.AlphaExample()
+ +

Freezing Pmw

+ +

Since the dynamic loader requires that Pmw be installed at run + time, it can not be used when freezing Pmw. In this case, a + single module containing all Pmw code is required, which can then + be frozen with the rest of the application's modules. The + bundlepmw.py script in the Pmw bin directory can be used to + create such a file. This script concatenates (almost) all Pmw + megawidget files into a single file, Pmw.py, which it writes to + the current directory. The script is called like this:

+ +
 bundlepmw.py [-noblt] [-nocolor] /path/to/Pmw/Pmw_X_X_X/lib
+ +

The last argument should be the path to the lib directory of the + required version of Pmw. By default, the Pmw.py file imports + the PmwBlt and PmwColor modules and so, to freeze an + application using Pmw, you will need to copy the files PmwBlt.py + and PmwColor.py to the application directory before freezing.

+ +

If you are sure that your application does not use any of the + Pmw.Blt or Pmw.Color functions, you can use the -noblt or + -nocolor options. In this case Pmw.py will be modified so + that it does not import these module(s) and so will not need to be + included when freezing the application.

+ +

If your application only uses a few Pmw megawidgets, you can + remove the references to the usused ones in the files list in + the bundlepmw.py code. To make the change, take a copy of the + script and modify it. This will make the Pmw.py file smaller. + However, be sure that you do not delete megawidgets that are + components or base classes of megawidgets that you use.

+ +

+ + + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/example.py b/Pmw/Pmw_1_2/doc/example.py new file mode 100644 index 00000000..0eed16fa --- /dev/null +++ b/Pmw/Pmw_1_2/doc/example.py @@ -0,0 +1,79 @@ +import Tkinter +import Pmw + +class ThresholdScale(Pmw.MegaWidget): + """ Megawidget containing a scale and an indicator. + """ + + def __init__(self, parent = None, **kw): + + # Define the megawidget options. + optiondefs = ( + ('colors', ('green', 'red'), None), + ('threshold', 50, None), + ('value', None, Pmw.INITOPT), + ) + self.defineoptions(kw, optiondefs) + + # Initialise base class (after defining options). + Pmw.MegaWidget.__init__(self, parent) + + # Create the components. + interior = self.interior() + + # Create the indicator component. + self.indicator = self.createcomponent('indicator', + (), None, + Tkinter.Frame, interior, + width = 16, + height = 16, + borderwidth = 2, + relief = 'raised') + self.indicator.grid() + + # Create the scale component. + self.scale = self.createcomponent('scale', + (), None, + Tkinter.Scale, interior, + command = self._doCommand, + tickinterval = 20, + length = 200, + from_ = 100, + to = 0, + showvalue = 0) + self.scale.grid() + + value = self['value'] + if value is not None: + self.scale.set(value) + + # Check keywords and initialise options. + self.initialiseoptions() + + def _doCommand(self, valueStr): + if self.scale.get() > self['threshold']: + color = self['colors'][1] + else: + color = self['colors'][0] + self.indicator.configure(background = color) + +Pmw.forwardmethods(ThresholdScale, Tkinter.Scale, 'scale') + +# Initialise Tkinter and Pmw. +root = Pmw.initialise() +root.title('Pmw ThresholdScale demonstration') + +# Create and pack two ThresholdScale megawidgets. +mega1 = ThresholdScale() +mega1.pack(side = 'left', padx = 10, pady = 10) + +mega2 = ThresholdScale( + colors = ('green', 'yellow'), + threshold = 75, + value = 80, + indicator_width = 32, + scale_width = 25) +mega2.pack(side = 'left', padx = 10, pady = 10) + +# Let's go. +root.mainloop() diff --git a/Pmw/Pmw_1_2/doc/example1.gif b/Pmw/Pmw_1_2/doc/example1.gif new file mode 100644 index 00000000..b54ca935 Binary files /dev/null and b/Pmw/Pmw_1_2/doc/example1.gif differ diff --git a/Pmw/Pmw_1_2/doc/example2.gif b/Pmw/Pmw_1_2/doc/example2.gif new file mode 100644 index 00000000..bd5889bd Binary files /dev/null and b/Pmw/Pmw_1_2/doc/example2.gif differ diff --git a/Pmw/Pmw_1_2/doc/exercises.py b/Pmw/Pmw_1_2/doc/exercises.py new file mode 100644 index 00000000..edd4f521 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/exercises.py @@ -0,0 +1,123 @@ +import Tkinter +import Pmw + +class ThresholdScale(Pmw.MegaWidget): + """ Megawidget containing a scale and an indicator. + """ + + def __init__(self, parent = None, **kw): + # Define the megawidget options. + optiondefs = ( + ('colors', ('green', 'red'), None), + ('orient', 'vertical', Pmw.INITOPT), + ('labelmargin', 0, Pmw.INITOPT), + ('labelpos', None, Pmw.INITOPT), + ('threshold', (50,), None), + ('value', None, Pmw.INITOPT), + ) + self.defineoptions(kw, optiondefs) + + # Initialise base class (after defining options). + Pmw.MegaWidget.__init__(self, parent) + + # Create the components. + interior = self.interior() + + # Create the indicator component. + self.indicator = self.createcomponent('indicator', + (), None, + Tkinter.Frame, interior, + width = 16, + height = 16, + borderwidth = 2, + relief = 'raised') + + # Create the value component. + self.value = self.createcomponent('value', + (), None, + Tkinter.Label, interior, + width = 3) + + # Create the scale component. + if self['orient'] == 'vertical': + # The default scale range seems to be + # the wrong way around - reverse it. + from_ = 100 + to = 0 + else: + from_ = 0 + to = 100 + + self.scale = self.createcomponent('scale', + (), None, + Tkinter.Scale, interior, + orient = self['orient'], + command = self._doCommand, + tickinterval = 20, + length = 200, + from_ = from_, + to = to, + showvalue = 0) + + value = self['value'] + if value is not None: + self.scale.set(value) + + # Use grid to position all components + if self['orient'] == 'vertical': + self.indicator.grid(row = 1, column = 1) + self.value.grid(row = 2, column = 1) + self.scale.grid(row = 3, column = 1) + # Create the label. + self.createlabel(interior, childRows=3) + else: + self.indicator.grid(row = 1, column = 1) + self.value.grid(row = 1, column = 2) + self.scale.grid(row = 1, column = 3) + # Create the label. + self.createlabel(interior, childCols=3) + + # Check keywords and initialise options. + self.initialiseoptions() + + def _doCommand(self, valueStr): + valueInt = self.scale.get() + colors = self['colors'] + thresholds = self['threshold'] + color = colors[-1] + for index in range(len(colors) - 1): + if valueInt <= thresholds[index]: + color = colors[index] + break + self.indicator.configure(background = color) + self.value.configure(text = valueStr) + +Pmw.forwardmethods(ThresholdScale, Tkinter.Scale, 'scale') + +# Initialise Tkinter and Pmw. +root = Pmw.initialise() +root.title('Pmw ThresholdScale demonstration') + +# Create and pack two ThresholdScale megawidgets. +mega1 = ThresholdScale(scale_showvalue = 1) +mega1.pack(side = 'left', padx = 10, pady = 10) + +mega2 = ThresholdScale( + colors = ('green', 'yellow', 'red'), + threshold = (50, 75), + value = 80, + indicator_width = 32, + scale_width = 25) +mega2.pack(side = 'left', padx = 10, pady = 10) + +# Create and pack two horizontal ThresholdScale megawidgets. +mega3 = ThresholdScale( + orient = 'horizontal', + labelpos = 'n', + label_text = 'Horizontal') +mega3.pack(side = 'top', padx = 10, pady = 10) +mega4 = ThresholdScale(orient = 'horizontal') +mega4.pack(side = 'top', padx = 10, pady = 10) + +# Let's go. +root.mainloop() diff --git a/Pmw/Pmw_1_2/doc/features.html b/Pmw/Pmw_1_2/doc/features.html new file mode 100644 index 00000000..055cce7b --- /dev/null +++ b/Pmw/Pmw_1_2/doc/features.html @@ -0,0 +1,87 @@ + + + + + + Pmw features + + + + +

Pmw features

+ +

+ Pmw is a toolkit for building high-level compound widgets, or + megawidgets, constructed using other widgets as component parts. + It promotes consistent look and feel within and between graphical + applications, is highly configurable to your needs and is easy to + use.

+ +

Pmw consists of:

+
  • A few base classes, providing a foundation for building + megawidgets.

    + +
  • +
  • A library of flexible and extensible megawidgets built on + the base classes, such as buttonboxes, notebooks, + comboboxes, selection widgets, paned widgets, scrolled + widgets and dialog windows.

    + +
  • +
  • A lazy importer/dynamic loader which is automatically + invoked when Pmw is first imported. This gives unified + access to all Pmw classes and functions through the Pmw. + prefix. It also speeds up module loading time by only + importing Pmw sub-modules when needed.

    + +
  • +
  • Complete reference documentation, covering all classes and + functions including all megawidgets and their options, + methods and components. Helpful tutorial material is also + available.

    + +
  • +
  • A test framework and tests for Pmw megawidgets.

    + +
  • +
  • A slick demonstration of the megawidgets.

    + +
  • +
  • An interface to the BLT busy, graph and vector commands.

    + +
+ +

The interface to Pmw megawidgets is similar to basic Tk widgets, so it + is easy for developers to include both megawidgets and basic Tk + widgets in their graphical applications. In addition, Pmw + megawidgets may themselves be extended, using either inheritance or + composition.

+ +

The use of the Pmw megawidgets replaces common widget combinations + with higher level abstractions. This simplifies code, making it + more readable and maintainable. The ability to extend Pmw + megawidgets enables developers to create new megawidgets based on + previous work.

+ +

+ + + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/halfblueball.gif b/Pmw/Pmw_1_2/doc/halfblueball.gif new file mode 100644 index 00000000..6977920d Binary files /dev/null and b/Pmw/Pmw_1_2/doc/halfblueball.gif differ diff --git a/Pmw/Pmw_1_2/doc/howtobuild.html b/Pmw/Pmw_1_2/doc/howtobuild.html new file mode 100644 index 00000000..4a408b48 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/howtobuild.html @@ -0,0 +1,465 @@ + + + + + + How to build Pmw megawidgets + + + + +

How to build Pmw megawidgets

+ +

+ +

+ +
+

Introduction

+

+ This document briefly describes how to design and code Pmw + megawidgets by inheriting from the Pmw base classes. It shows step + by step how to build a simple example megawidget. This megawidget + allows the user to select one of a range of numbers and it also + indicates if the selected number is greater than a given threshold. + +

+ +
+

Choosing the components

+ +

+ The megawidget will be built using a Tkinter.Scale widget to allow + the user to select a number in a range, and a Tkinter.Frame widget + to act as an indicator, displaying red (say) if the selected number + exceeds the threshold. It will look something like this: + +

+ +

+ Scale 2 +

+ +

+ The programmer using this megawidget will need access to the scale + widget, since they will need to set the scale's range. Therefore + the scale will be made a component of the megawidget. The + programmer will probably not need access to the indicator frame, + but, just in case the need arises to change the borderwidth or + relief of the indicator, we will make it a component too. This + illustrates a convention about components - for maximum + configurability, make all sub-widgets components. + +

+ +
+

Choosing the options

+ +

+ Apart from the component options now available through the scale and indicator + components, the megawidget will need a few options of its own. It + will need a threshold option to set the threshold. + It may also need options to set the colors of the indicator when the + selected value is both above and below the threshold. Other options + could be orient or indicatorpos to + specify the relative position of components and + margin, padx or + pady to specify spacing between and around the + components. For this example, we will define three options - + threshold, colors and + value. The colors option will be + a 2-element sequence specifying two colors (below threshold, above + threshold). The value option will be the initial + value of the scale. + +

+ +
+

Coding the megawidget

+ +

+ The first things to do are to decide on a name for the new + megawidget, decide which base class to inherit from and to begin to + write the constructor. Most Pmw megawidgets are derived from either + Pmw.MegaWidget, Pmw.MegaToplevel or Pmw.Dialog. In this case, since + the widget is not to be contained within its own toplevel window, we + will inherit from Pmw.MegaWidget. The constructors of megawidgets + take one argument (the widget to use as the parent of the + megawidget's hull, defaulting to the root window) and any number of + keyword arguments. + +

+ +
+class ThresholdScale(Pmw.MegaWidget):
+    """ Megawidget containing a scale and an indicator.
+    """
+ 
+    def __init__(self, parent = None, **kw):
+
+ +

+ Next, we need to define the options supplied by this megawidget. + Each option is specified by a 3-element sequence. The first element + is the option's name. The second element is the default value. The + third element is either a callback function, + Pmw.INITOPT or None. In the first + case, the function is called at the end of construction (during the + call to self.inialiseoptions) and also + whenever the option is set by a call to + configure. Pmw.INITOPT indicates that + the option is an initialisation option - it cannot be set by calling + configure. None indicates that the + option can be set by calling configure, but that there + is no callback function. + +

+ +

+ The call to self.defineoptions also includes the + keyword arguments passed in to the constructor. The value given to + any option specified in the keywords will override the default + value. + +

+ +
+        # Define the megawidget options.
+        optiondefs = (
+            ('colors',    ('green', 'red'), None),
+            ('threshold', 50,               None),
+            ('value',     None,             Pmw.INITOPT),
+        )
+        self.defineoptions(kw, optiondefs)
+
+ +

+ After defining the options, the constructor of the base class should + be called. The options need to be defined first so that a derived + class can redefine the default value of an option defined in a base + class. This is because the value specified by the derived class + must be made available before the base class constructor is called. + The keyword + arguments should not be passed into the base class constructor since + they have already been dealt with in the previous step. + +

+ +
+        # Initialise base class (after defining options).
+        Pmw.MegaWidget.__init__(self, parent)
+
+ +

+ Now we should create the components. The components are created as + children (or grandchildren ...) of the megawidget's interior. + +

+ +
+        # Create the components.
+        interior = self.interior()
+
+ +

+ The first component to create is the indicator. The + createcomponent method creates the sub-widget and + registers the widget as a component of this megawidget. It takes + five arguments plus any number of keyword arguments. The arguments + are name, aliases, group, class and constructor arguments. See the + Pmw.MegaArchetype reference manual) + for full details. + +

+ +
+        # Create the indicator component.
+        self.indicator = self.createcomponent('indicator',
+                (), None,
+                Tkinter.Frame, (interior,),
+                        width = 16,
+                        height = 16,
+                        borderwidth = 2,
+                        relief = 'raised')
+        self.indicator.grid()
+
+ +

+ The scale component is created in a similar way. In this case, the + initial value of the scale is also set to the value of the + value initialisation option. + +

+ +
+        # Create the scale component.
+        self.scale = self.createcomponent('scale',
+                (), None,
+                Tkinter.Scale, (interior,),
+                        command = self._doCommand,
+                        tickinterval = 20,
+                        length = 200,
+                        from_ = 100,
+                        to = 0,
+                        showvalue = 0)
+        self.scale.grid()
+ 
+        value = self['value']
+        if value is not None:
+            self.scale.set(value)
+
+ +

+ At the end of the constructor, the initialiseoptions + method is called to check that all keyword arguments have been used + (that is, the caller did not specify any unknown or misspelled + options) and to call the option callback functions. + +

+ +
+        # Check keywords and initialise options.
+        self.initialiseoptions()
+
+ +

+ All other methods must now be defined. In this case, only one + method is required - a method called whenever the scale changes and + which sets the indicator color according to the threshold. + +

+ +
+    def _doCommand(self, valueStr):
+        if self.scale.get() > self['threshold']:
+            color = self['colors'][1]
+        else:
+            color = self['colors'][0]
+        self.indicator.configure(background = color)
+
+ +

+ To complete the megawidget, methods from other classes can be + copied into this class. In this case, all Tkinter.Scale methods + not already defined by the megawidget are made available as methods + of this class and are forwarded to the scale component. Note that + the third argument to Pmw.forwardmethods is the name of + the instance variable referring to the Tkinter.Scale widget and not + the name of the component. This function is called outside of and + after the class definition. + +

+ +
+Pmw.forwardmethods(ThresholdScale, Tkinter.Scale, 'scale')
+
+ +

+ Important note: If a megawidget defines options + using defineoptions(), then this method must be + called in the megawidget constructor before the call to the base + class constructor and a matching call to + initialiseoptions() must made at the end of the + constructor. For example: + +

+
+    def __init__(self, parent = None, **kw):
+	optionDefs = ...
+	self.defineoptions(kw, optionDefs)
+	BaseClass.__init__(self, parent)
+	...
+	self.initialiseoptions()
+
+ +
+

Creating instances of the megawidget

+ +

+ The code below creates two of our example megawidgets. The first is + created with default values for all options. The second is created + with new values for the options. It also redefines some of the + options of the components. + +

+ +
+
+
+# Create and pack two ThresholdScale megawidgets.
+mega1 = ThresholdScale()
+mega1.pack(side = 'left', padx = 10, pady = 10)
+
+mega2 = ThresholdScale(
+        colors = ('green', 'yellow'),
+        threshold = 75,
+        value = 80,
+        indicator_width = 32,
+        scale_width = 25)
+mega2.pack(side = 'left', padx = 10, pady = 10)
+
+
+
+ +

+ Scale 1 +

+ +
+

The complete code

+ +

+ The complete code for this example can be seen + here. + +

+ +
+

Exercises

+ +

+ These exercises build on the example presented so far. + +

+ +
    +
  1. + Change the call to create mega1 so that the scale + widget displays the current value next to the slider. (You may + need to look at the Tk scale manual page to find which option to + the scale component to set.) You will be able to + do this without modifying the ThresholdScale class code. + +
  2. +
  3. + Add a Tkinter.Label component between the indicator and scale + components. Modify the _doCommand method so that it + displays the current value of the scale in this label. + +
  4. +
  5. + Modify the colors and threshold + options so that they both accept a tuple. Now implement multiple + thresholds, so that the indicator displays one of several colors, + depending on the value of the scale. + +
  6. +
  7. + Add an orient initialisation option and lay out + the components horizontally or vertically depending on its value. + +
  8. +
  9. + Read the description of the createlabel() method in + the Pmw.MegaArchetype reference + manual and add labelpos and + labelmargin initialisation options which allow + the creation of a label for the megawidget. + +
  10. +
+ +

+ An example of how these changes can be made can be seen + here. + +

+ +
+

Contributing your megawidgets to Pmw

+ +

+ If you have completed a megawidget that may be useful to others, you + may like to consider contributing it to Pmw. See + Contributions welcome for + how to contribute. + +

+ +
+

Pmw coding conventions

+ +

+As a final note, the Pmw code makes an attempt to follow these coding +conventions. +

+ +
    +
  • + Class names: initial of each word is upper case (including first word). + +
  • +
  • + Public method and function names: all in lower case. + +
  • +
  • + Megawidget options: all in lower case. + +
  • +
  • + Megawidget component names: all in lower case. + +
  • +
  • + Function arguments: initial of each word is upper case (except first word). + +
  • +
  • + Private names: initial of each word is upper case (except first + word if not a class) + +
  • +
  • + Underscores as word separators are only used when overriding + Tkinter methods of same name. + +
  • +
  • + Indent is four spaces. + +
  • +
  • + Continuation lines are indented by eight spaces, so that they + won't be confused with a following nested code block. + Continuation lines should be used when a statement, which would + normally be written on one line, is longer than 80 characters. + Examples are "if" statements which contain many conditions and + function calls with many arguments. + +
  • +
  • + + Surround = with spaces when used with keyword + parameters in function calls. + +
  • +
  • + + Multi-line function calls should have one keyword parameter per + line. + +
  • +
+
+
+ + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/howtouse.html b/Pmw/Pmw_1_2/doc/howtouse.html new file mode 100644 index 00000000..f7e43b92 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/howtouse.html @@ -0,0 +1,719 @@ + + + + + + How to use Pmw megawidgets + + + + +

How to use Pmw megawidgets

+ +

+ +

+ +
+

Introduction

+

+ This document briefly describes the features of the Pmw megawidget + toolkit and how to use the megawidgets. Using examples, it + describes those features common to all Pmw megawidgets. For a + description of individual Pmw megawidgets see the + reference manuals. + For complete information on general Pmw megawidget functionality see the + Pmw.MegaArchetype reference manual. + For a lot more example code, run any of the files in the + Pmw demos directory. + +

+ +

+ A simple example of a megawidget is a counter. This widget + contains an entry field and two small arrow buttons. Users may + enter a value directly into the entry field or they may use the + buttons to increment and decrement the value displayed without + having to use the keyboard. Having this and other megawidgets in + your toolbox allows you to choose the best graphical interface for + your application. + +

+
+

Getting started

+ +Initialisation of Pmw +
+

+ To run the examples in the tutorial, make sure that the + Pmw lib directory is in sys.path. You + should be able to cut and paste the examples into an interactive + python session, or you can copy them to a file and run the file with + python. + +

+

+ The following two lines should be entered before any of the + examples. These import and initialise Pmw. + For more information on Pmw.initialise() see the + Pmw functions reference manual. + +

+ +
+
+
+import Pmw
+root = Pmw.initialise()
+
+
+
+ +

+ If necessary, you can have more control over how Tkinter and Pmw are + initialised by using this form of initialisation: + +

+ +
+
+
+import Tkinter
+root = Tkinter.Tk()
+import Pmw
+Pmw.initialise(root)
+
+
+
+ +
+

Megawidget construction

+ +Creating a counter +
+

+ Now that you have the formalities out of the way, you can create and + pack a counter megawidget (see + Pmw.Counter reference manual) using + its default configuration like this: + +

+ +
+
+
+counter1 = Pmw.Counter()
+counter1.pack(padx = 10, pady = 10)
+
+
+
+ +

+ Now enter a number and click on the arrow buttons to see the number + increment or decrement. The result looks something like this: + +

+ +

+ Counter 1 +

+ +

+ The above example creates the counter as a child of the root window. + If you want to create it as a child of another window (for example, + a Tkinter.Frame widget called 'frame'), add the parent as an + argument to the constructor: + +

+ +
+
+
+counter1a = Pmw.Counter(frame)
+
+
+
+ +
+

Methods

+

+ Once a megawidget has been created, you can call any of its other + methods in a similar way to Tk widgets. The following sets the value + of the counter and then increments it: +

+ +
+
+
+counter1.setentry(41)
+counter1.increment()
+
+
+
+ +
+

Options

+

+ Like any widget, a megawidget may have options to allow it to be + configured for a particular use. Options allow the megawidget user + to modify the appearance and behaviour of the megawidget. The + counter megawidget has several such options. One of them, + datatype, specifies how the counter should count up + and down, such as, for example, by integers, reals, times or dates. + The default value is 'numeric', which means the + counter expects integers to be entered and will support + incrementing and decrementing by whole numbers. + +

+ +

+ Another option is + increment, which specifies how many units should be + added or subtracted when the counter is incremented or decremented. + Using these options, you can create a time counter, supporting the + format HH:MM:SS, and counting in minutes, like + this (note also the call to the setentry method to set + the contents of the entry field): + +

+ +
+
+
+counter2 = Pmw.Counter(
+    datatype = 'time',
+    increment = 60)
+counter2.setentry('00:00:00')
+counter2.pack(padx = 10, pady = 10)
+
+
+
+ +

+ Many megawidget options can be modified using the + configure() method. For example, you can change the + value of the increment option to 10 minutes like + this: + +

+ +
+
+
+counter2.configure(increment = 60 * 10)
+
+
+
+ +Initialisation options +
+

+ Some megawidget options can only be set when creating the megawidget. + These options can not be set by calling the configure() + method, but they can be queried in all the usual ways. For example, + the counter has an orient initialisation option + which specifies whether the arrow buttons should appear to the + left and right of the entry field ('horizontal') + or above and below ('vertical'). You can create a + numeric counter with arrow buttons above and below the entry + field like this: + +

+ +
+
+
+counter3 = Pmw.Counter(orient = 'vertical')
+counter3.pack(padx = 10, pady = 10)
+
+
+
+ +Querying options +
+

+ You can query the value of megawidget options (initialisation or + not) in similar ways as for normal Tkinter widgets. For example, + the following code prints the values of some of the counter options. + +

+ +
+
+
+print counter3.cget('increment')
+    --> 1
+print counter3.configure('orient')
+    --> ('orient', 'orient', 'Orient', 'horizontal', 'vertical')
+
+
+
+ +

+ When a Tk widget option is queried, its value is always + returned as a string, regardless of the type used when setting the + option. However, when a Pmw megawidget option is queried, a + reference to the object used when setting the option is returned. + In other words it is not always a string. For example, the type + returned by cget('increment') above was integer. + +

+ +
+

Components

+

+ Megawidgets are made up of other widgets, which we call + components. Each component is known by a logical name and + may be either a simple Tk widget, or may itself be a megawidget. + Pmw gives the megawidget user access to not only the functionality + supported directly by the megawidget through its options and methods, + but also to the components of the megawidget and their options and + methods. To access a component directly, use the + component() method. For example, to call method + doit of component comp + of megawidget mega: + +

+ +
+
+
+mega.component('comp').doit()
+
+
+
+ +Component options +
+

+ There is a short-hand way to access the options of components, by + using the notation component_option. This allows, for + example, a counter megawidget to be configured with different + colored backgrounds for each of its arrow button components (these + components are called downarrow and + uparrow): + +

+ +
+
+
+counter2.configure(
+    downarrow_background = 'green',
+    uparrow_background = 'red')
+
+
+
+ +The hull +
+

+ All megawidgets are enclosed in a containing widget which is created + automatically by the Pmw base classes. For normal megawidgets the + container is a Tkinter Frame widget. For megawidgets which are + toplevel windows, the container is a Tkinter Toplevel widget. The + containing widget is accessible as the hull + component. + +

+ +

+ To access options of the containing widget use the form + hull_option. For example to create a + counter megawidget with a wide sunken border around it: + +

+ +
+
+
+counter4 = Pmw.Counter(
+    hull_relief = 'sunken',
+    hull_borderwidth = 5 
+)
+
+
+
+ + +The interior +
+

+ Some megawidgets, such as Dialog and LabeledWidget, also have a + frame into which users can pack other widgets. This frame may be a + component but can also be accessed with the interior() + method. For the Pmw.MegaToplevel and Pmw.MegaWidget classes, the + interior widget is the same as the hull widget. For other + megawidgets, the hull is the outer, containing widget and the + interior is the empty frame which can be used to extend the + megawidget by including extra internal widgets. + +

+ +Sub components and aliases +
+

+ Components may themselves be megawidgets and so their + (sub-)components can be referred to using the notation + component_sub-component. For example, the + entryfield component of the counter is a + Pmw.EntryField megawidget (which handles the input validation). In + turn, this has a Tkinter.Entry component named + entry. Therefore, you can change the background of + the counter's Tkinter.Entry widget with: + +

+ +
+
+
+counter2.configure(entryfield_entry_background = 'yellow')
+
+
+
+ +

+ Most component path names (like entryfield_entry) + have a shorter alias defined for them. In this + case, you can use the equivalent: + +

+ +
+
+
+counter2.configure(entry_background = 'yellow')
+
+
+
+ +Changing the python class of a component +
+

+ Each megawidget component is an instance of some python class. The + default class of each component is given in the reference manual. + By using the special pyclass component option, you + can specify a different python class to use when creating the + component. For example, to create a Pmw.Counter megawidget which + has a Tkinter.Button as its label, rather than the default + Tkinter.Label: + +

+ +
+
+
+counter5 = Pmw.Counter(
+        labelpos = 'w',
+        label_text = 'Hello',
+        label_pyclass = Tkinter.Button
+)
+
+
+
+
+ +
+

Forwarding methods

+

+ Since a Pmw megawidget is a normal python class, it both inherits + methods from its base classes and also may have other methods + defined for it in the usual way. + Pmw also supports a third way that a megawidget may gain methods - + by 'forwarding' methods to one or more of its subwidgets. This is + also known as 'delegating'. + For example, a Pmw.Counter megawidget delegates the methods related + to its Pmw.EntryField component, entryfield, to the + component. It does not have to explicitely define methods which + call the component methods. + This is why we can call counter2.setentry() - since + setentry() is a method of the Pmw.EntryField + component, it is available to the Pmw.Counter. + +

+

+ Methods already defined by a class or its base classes take + precedence over delegated methods. For example, Pmw.Counter + inherits a cget method from Pmw.MegaArchetype. + Therefore, this method is not delegated to the cget + method of Pmw.EntryField. + +

+ +
+

Extending Pmw megawidgets

+ +

+ There are several ways of extending Pmw megawidgets. Firstly, the + flexibility of the options and components allows the widget's + appearance and behaviour to be greatly modified. Secondly, widgets + of the user's choice can be added inside some megawidgets by using + the interior() method. The Pmw classes MegaToplevel, MegaWidget, + Dialog and LabeledWidget are particularly designed to be extended in + this way. For example, to create a dialog window containing a + counter: + +

+ +
+
+
+dialog = Pmw.Dialog(
+        title = 'Counter dialog',
+        buttons = ('OK', 'Cancel'))
+interior = dialog.interior()
+counter = Pmw.Counter(interior)
+counter.pack(padx = 20, pady = 20)
+
+
+
+ +

+ Counter 2 +

+ +

+ A third way to extend megawidgets is to inherit from (or subclass) + them. See How to build Pmw + megawidgets for information on how to use inheritance to extend + a megawidget by adding new options. For simpler cases, where new + methods are to be added to an existing megawidget and/or the default + values for some options are to be changed, normal subclassing can be + used. For example, to create new classes based on a Pmw.Counter, + one with a new method getminutes() and one with a + default datatype of 'time' and a white entry background: + +

+ +
+
+
+class MinuteCounter1(Pmw.Counter):
+
+    def getminutes(self):
+	return Pmw.timestringtoseconds(self.getvalue()) / 60
+
+class MinuteCounter2(Pmw.Counter):
+
+    def __init__(self, parent = None, **kw):
+        kw['datatype'] = 'time'
+        kw['entry_background'] = 'white'
+        kw['entryfield_value'] = '00:00:00'
+        kw['increment'] = 60
+	apply(Pmw.Counter.__init__, (self, parent), kw)
+
+
+
+ +
+

A quick example

+

+ The following code is a small example of how to use Pmw megawidgets. + It is a complete program which displays three ways for the user to + enter a value - using an up-down counter, an entry field with + validation and a dropdown combobox. + +

+
+
+
+import Pmw
+root = Pmw.initialise(fontScheme = 'pmw1')
+
+counter = Pmw.Counter(
+        label_text = 'Counter:',
+        labelpos = 'w',
+        entryfield_value = '00:00:00',
+        entryfield_validate = 'time',
+        datatype='time',
+        increment=5*60,
+)
+counter.pack(fill = 'x', padx = 10, pady = 10)
+
+entry = Pmw.EntryField(
+        label_text = 'Real entry:',
+        labelpos = 'w',
+        value = '+2.9979e+8',
+        validate = 'real',
+)
+entry.pack(fill = 'x', padx = 10, pady = 10)
+
+combo = Pmw.ComboBox(
+        label_text = 'ComboBox:',
+        labelpos = 'w',
+        scrolledlist_items = map(str, range(20))
+)
+combo.pack(fill = 'x', padx = 10, pady = 10)
+
+# Make the labels line up neatly
+Pmw.alignlabels((counter, entry, combo))
+
+root.title('Pmw megawidgets example')
+root.mainloop()
+
+
+
+ +

+ Example 1 +

+ +
+

Another example

+

+ The following also shows how to use Pmw megawidgets. It displays a + RadioSelect megawidget and an exit button packed into the root + window. + +

+ +
+
+
+import Tkinter
+import Pmw
+
+def callback(tag):
+    # This is called whenever the user clicks on a
+    # button in the RadioSelect widget.
+    print tag, 'was pressed.'
+
+# Initialise Tkinter and Pmw.
+root = Pmw.initialise(fontScheme = 'pmw1')
+root.title('Pmw RadioSelect demonstration')
+
+# Create and pack a RadioSelect widget.
+radio = Pmw.RadioSelect(
+        command = callback,
+        labelpos = 'w',
+        label_text = 'Food group:')
+radio.pack(padx = 20, pady = 20)
+
+# Add some buttons to the RadioSelect.
+for text in ('Fruit', 'Vegetables', 'Cereals', 'Legumes'):
+    radio.add(text)
+radio.invoke('Vegetables')
+
+# Create an exit button.
+exit = Tkinter.Button(text = 'Exit', command = root.destroy)
+exit.pack(pady = 20)
+
+# Let's go.
+root.mainloop()
+
+
+
+ +

+ Example 2 +

+ +
+

Using the Tk option database

+

+ There are several ways to use the Tk option database to customise a + Pmw application. Firstly you can customise all the basic Tk widgets + in the usual way. For example, to set the background of all + Tkinter.Label widgets (whether a megawidget component or not): + +

+ +
+
+
+root.option_add('*Label.background', 'pink')
+
+
+
+ +

+ To set the background of all Pmw.EntryField label + components: + +

+ +
+
+
+root.option_add('*EntryField.Label.background', 'green')
+
+
+
+ +

+ To set the background of all Pmw.EntryField components, including + the hull component: + +

+ +
+
+
+root.option_add('*EntryField*background', 'blue')
+
+
+
+ +

+ The above option settings affect basic Tk widgets and, since it is + built into the Tk widgets, this functionality is always available. + However, to be able to use the Tk option database to set the default + values for Pmw megawidget options, Pmw.initialise() + must be called with useTkOptionDb = 1. If this is not + done, Pmw does not query the Tk option database for megawidget + option defaults. This is the default behaviour because there is a + slight performance penalty for using the Tk option database. + +

+ +

+ Assuming useTkOptionDb has been set, the default + buttonbox position of all Pmw.Dialog megawidgets can be changed + with: + +

+ +
+
+
+root.option_add('*Dialog.buttonboxpos', 'e')
+
+
+
+ +

+ To set the label position of all Pmw.EntryField megawidgets, thus giving + them a label component by default: + +

+ +
+
+
+root.option_add('*EntryField.labelpos', 'w')
+
+
+
+ +
+
+ + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/index.html b/Pmw/Pmw_1_2/doc/index.html new file mode 100644 index 00000000..ef531a23 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/index.html @@ -0,0 +1,131 @@ + + + + + + Pmw megawidgets 1.2 + + + + +

Pmw 1.2

+ +

Python megawidgets

+ +

+ +

+ +

+Pmw is a toolkit for building high-level compound widgets in Python +using the Tkinter module. +

+ +

+It consists of a set of base classes and a library of +flexible and extensible megawidgets built on this foundation. These +megawidgets include notebooks, comboboxes, selection widgets, paned +widgets, scrolled widgets, dialog windows, etc. + +

+ +

+Local documentation +

+ +
+
+ + + Main features +
+ Getting started - including downloading + and installation +
+ How to use Pmw megawidgets - creating + and configuring megawidgets +
+ How to build Pmw megawidgets - inheriting + (sub-classing) from Pmw megawidgets +
+ Demonstrations and tests - how to run +
+ Dynamic loader - also discusses how + to "freeze" Pmw +
+ Reference manuals - complete documentation + of all Pmw classes and functions +
+ Porting between different versions of Pmw +
+ Change log +
+ Todo list and list of known bugs +
+ Copyright +
+
+ +

+External links +

+ +
+
+ + + Pmw project home page + on SourceForge - contains CVS source repository, bug tracking, + release distributions, mailing list, etc + +
+ Pmw-general + mailing list - subscribe to this list to get announcements of + Pmw releases and general discussion on Pmw + +
+ A User's Guide + to Pmw.Blt + - an excellent tutorial and reference covering the Pmw interface + to the powerful Blt graph widget, written by Bjørn Ove Thue + and Hans Petter Langtangen. You can also download the full + HTML document for local viewing. + +
+
+ +

+See the +Pmw megawidgets home page +for the latest information about Pmw. + +

+ +

+ +Comments, bugs, fixes to the Pmw +discussion and announcement mailing list. + +

+ + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/porting.html b/Pmw/Pmw_1_2/doc/porting.html new file mode 100644 index 00000000..64a7cb5d --- /dev/null +++ b/Pmw/Pmw_1_2/doc/porting.html @@ -0,0 +1,325 @@ + + + + + + Porting between different versions of Pmw + + + + +

Porting between different versions of Pmw

+ +

+ This document contains a brief guide to porting existing code + between different versions of Pmw. It includes significant + functionality changes but does not include bug fixes or compatible + enhancements. For details of all changes, see + Changes to Pmw versions.

+ +

Porting from 0.8.5 to 1.0, 1.1 and 1.2

+ +
  • Bug fix, documention and new features only. No + backwards-incompatible changes.

    + +
+

Porting from 0.8.4 to 0.8.5

+ +
  • Bug fix release only. No interface changes.

    + +
+

Porting from 0.8.3 to 0.8.4

+ +
  • Change the setnaturalpagesize() method of Pmw.NoteBook to + setnaturalsize() (to be consistent with Pmw.PanedWidget).

    + +
  • +
  • Change Pmw.excludefrombusycursor() to Pmw.setbusycursorattributes(). + Replace busyCursorName option of Pmw.initialise() with + cursorName attribute of Pmw.setbusycursorattributes().

    + +
  • +
  • Several rarely used key bindings for Pmw.ScrolledListBox were + removed, changing the behaviour of the megawidget.

    + +
+

Porting from 0.8.1 to 0.8.3

+ +
  • The megawidgets Pmw.NoteBookR and Pmw.NoteBookS have been + replaced by a new Pmw.NoteBook. The interfaces are not + compatible, so see the Pmw.NoteBook reference manual for + details.

    + +
  • +
  • Change the get() method of Pmw.OptionMenu to getcurselection() + and the remove() method of Pmw.PanedWidget to delete().

    + +
  • +
  • If you use 'end', 'default' or None in calls to the + index() method of several megawidgets, change these to + Pmw.END, Pmw.DEFAULT and Pmw.SELECT, respectively.

    + +
  • +
  • The exclude argument has been removed from Pmw.showbusycursor(). + Use Pmw.excludefrombusycursor() instead.

    + +
  • +
  • The names of some of the positional arguments in the following + methods have changed: MegaArchetype.createcomponent(), + ButtonBox.insert(), ButtonBox.add(), MenuBar.addcascademenu(), + MenuBar.addmenuitem() and RadioSelect.add().

    + +
  • +
  • The Pmw.maxfontwidth() function has been removed. Use the + font_measure() Tkinter method, or if that has not yet been + implemented:

    +
     someWidget.tk.call('font', 'measure', someFont, 'W')
    + + +
  • +
  • The Pmw.fontexists() function has been removed. This is + because, since Tk8.0, all fonts exist, so it no longer has + any meaning.

    + +
+

Porting from 0.8 to 0.8.1

+ +
  • The Blt.Graph now supports blt2.4i which is not backwards + compatible with blt2.1.

    + +
+

Porting from 0.7 to 0.8

+ +
  • The format argument of Pmw.datestringtojdn() now defaults to + 'ymd'. If you want to display dates with year, month and day + in a different order, add a format option to + Pmw.datestringtojdn() or to the datatype option of Pmw.Counter + or the validate option of Pmw.EntryField.

    + +
  • +
  • The justify() method from Pmw.ScrolledListBox has been removed. + Use the xview() or yview() methods instead.

    + +
  • +
  • Replace the getFrame() method of Pmw.ScrolledFrame with the + interior() method.

    + +
  • +
  • Replace the ringpadx and ringpady options of Pmw.Group by + padding the megawidget itself or by padding the children of the + megawidget.

    + +
  • +
  • Replace the canvasbind() and canvasunbind() methods of + Pmw.Balloon with tagbind() and tagunbind().

    + +
  • +
  • The return value of Pmw.EntryField command callback is now + ignored. Previously, if the callback destroyed the megawidget, + it was required to return the string 'break', to work around a + problem in the event handling mechanism in Tkinter. With python + 1.5.2, Tkinter has been fixed. Therefore, user-supplied + callback functions should use Pmw.hulldestroyed to check if the + megawidget has been destroyed before performing any operations + on it.

    + +
  • +
  • If you require the 'pmw1' fontScheme when running under + Microsoft Windows and Macintosh, you will need to set the Tk + font options manually.

    + +
+

Porting from 0.6 to 0.7

+ +
  • Replace the maxwidth option of Pmw.EntryField with the 'max' + field of the validate option.

    + +
  • +
  • To specify that there should be no validation performed for a + Pmw.EntryField, the validate option must be None, not '' as + before.

    + +
  • +
  • The date and time values of the Pmw.EntryField validate option + (such as 'date_dmy' and 'time24', etc) are no longer supported. + Instead use a dictionary as the value of the validate option + with 'date' or 'time' in the 'validator' field. Include + other fields in the dictionary to further specify the + validation.

    + +
  • +
  • Pmw.Counter no longer supports the old date and time values for + the datatype option. Use a dictionary with a 'counter' + field of 'date' or 'time' and other fields to further + specify the counting.

    + +
  • +
  • Pmw.Counter no longer supports the min and max options. Use + the Pmw.EntryField validate option instead.

    + +
  • +
  • The bbox method of Pmw.ScrolledListBox now refers to the bbox + method of the listbox component, not the hull component.

    + +
  • +
  • By default, Pmw.MenuBar now automatically adds hotkeys to menus + and menu items for keyboard traversal. To turn this off, use the + hotkeys = 0 option.

    + +
  • +
  • The createcomponent() method now disallows the creation of + component names containing an underscore. If any component + names contain an underscore, rename them.

    + +
+

Porting from 0.5 to 0.6

+ +

To port applications using Pmw version 0.5 to version 0.6, make + sure you are using python1.5. Then, simply change any lines in + your application like this:

+ +
 from PmwLazy import Pmw
+ +

to this:

+ +
 import Pmw
+ +

Also, if you have added the lib directory of a specific version + of Pmw to sys.path or PYTHONPATH, this can be removed, as long + as Pmw can now be found from the default path, such as in the + python site-packages directory.

+ +

Porting from 0.2 to 0.4

+ +
  • To get Pmw.0.2 default fonts (helvetica with bold italic menus + and italic scales) initialise with:

    +
     Pmw.initialise(fontScheme = 'pmw1')
    + +

    If no fontScheme is given, the standard Tk default fonts are used.

    + + +
  • +
  • Remove all calls to setdefaultresources(), usual(), keep(), + renameoptions(), ignore() and defineoptiontypes().

    + +
  • +
  • Move call to defineoptions() to before call to base class + constructor, create optiondefs tuple from self.defineoptions + arguments, then call defineoptions().

    + +
  • +
  • Remove resource class and name from optiondefs.

    + +
  • +
  • The last element in the optiondefs tuple (callback function) + must be given (may be None).

    + +
  • +
  • Add to classes currently without any options:

    +
     optiondefs = ()
    + self.defineoptions(kw, optiondefs)
    + + +
  • +
  • Use createcomponent() to create components - this replaces the + calls to the component widget constructor and to + registercomponent().

    + +
  • +
  • Do not inherit from Pmw.LabeledWidget. Instead, replace with + Pmw.MegaWidget with labelpos and labelmargin options and a call + to self.createlabel(). If calling createlabel(), must replace + pack() with grid().

    + +
  • +
  • When calling a megawidget constructor, include subcomponent name when + setting subcomponent options (eg labeltext -> label_text)

    + +
  • +
  • The items option of ScrolledListBox is an initialisation option + only - use setlist() method after initialisation.

    + +
  • +
  • The autorelief option for Counter, EntryField, ScrolledText, + TextDialog has been removed.

    + +
  • +
  • ScrolledListBox.getcurselection() always returns a tuple of strings, + possibly of zero length.

    + +
  • +
  • Counter increment is always initialised to 1.

    + +
  • +
  • The 'time' Counter datatype option has been replaced by + 'timeN' and 'time24'.

    + +
  • +
  • The 'time' EntryField validate option has been replaced by + 'timeN' and 'time24'.

    + +
  • +
  • Replace call to initialise() with initialiseoptions(), removing + "kw" arg. This should always be the last line in a megawidget + constructor.

    + +
  • +
  • Replace hide() with withdraw().

    + +
  • +
  • Now need iconpos option for MessageDialogs with icon_bitmap option set.

    + +
  • +
  • Example megawidget class definition:

    + +
+
class MyBigWidget(Pmw.MegaWidget):
+    def __init__(self, parent = None, **kw):
+
+        # Define the megawidget options.
+        optiondefs = (
+            ('errorbackground',   'pink',      None),
+            ('maxwidth',          0,           self._myfunc),
+            ('myinit',            'good',      Pmw.INITOPT),
+        )
+        self.defineoptions(kw, optiondefs)
+
+        # Initialise the base class (after defining the options).
+        Pmw.MegaWidget.__init__(self, parent)
+
+        # Create the components.
+        interior = self.interior()
+        self._widget = self.createcomponent('component',
+                (('alias', 'component_alias'),), None,
+                Tkinter.Button, (interior,))
+        self._widget.grid(column=0, row=0, sticky='nsew')
+
+        self.createlabel(interior)
+
+        # Initialise instance variables.
+        self.deriveddummy = None
+
+        # Check keywords and initialise options.
+        self.initialiseoptions(MyBigWidget)
+
+ + + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/refindex.html b/Pmw/Pmw_1_2/doc/refindex.html new file mode 100644 index 00000000..19a549e0 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/refindex.html @@ -0,0 +1,79 @@ + + + + + + Pmw reference manual index + + + + +

Pmw reference manual
index

+ + +

+ +

+ +
Base classes
+Pmw.MegaArchetype +Pmw.MegaWidget +Pmw.MegaToplevel +
+
Widgets
+Pmw.ButtonBox +Pmw.ComboBox +Pmw.Counter +Pmw.EntryField +Pmw.Group +Pmw.HistoryText +Pmw.LabeledWidget +Pmw.MainMenuBar +Pmw.MenuBar +Pmw.MessageBar +Pmw.NoteBook +Pmw.OptionMenu +Pmw.PanedWidget +Pmw.RadioSelect +Pmw.ScrolledCanvas +Pmw.ScrolledField +Pmw.ScrolledFrame +Pmw.ScrolledListBox +Pmw.ScrolledText +Pmw.TimeCounter +
+
Dialogs
+Pmw.AboutDialog +Pmw.ComboBoxDialog +Pmw.CounterDialog +Pmw.Dialog +Pmw.MessageDialog +Pmw.PromptDialog +Pmw.SelectionDialog +Pmw.TextDialog +
+
Miscellaneous
+Pmw.Balloon +Pmw.Blt +Pmw.Color +Module functions +
+ +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/scale1.gif b/Pmw/Pmw_1_2/doc/scale1.gif new file mode 100644 index 00000000..5cf5d60b Binary files /dev/null and b/Pmw/Pmw_1_2/doc/scale1.gif differ diff --git a/Pmw/Pmw_1_2/doc/scale2.gif b/Pmw/Pmw_1_2/doc/scale2.gif new file mode 100644 index 00000000..5682715e Binary files /dev/null and b/Pmw/Pmw_1_2/doc/scale2.gif differ diff --git a/Pmw/Pmw_1_2/doc/starting.html b/Pmw/Pmw_1_2/doc/starting.html new file mode 100644 index 00000000..be447450 --- /dev/null +++ b/Pmw/Pmw_1_2/doc/starting.html @@ -0,0 +1,382 @@ + + + + + + Getting started with Pmw + + + + +

Getting started with Pmw

+ +

+ +

+ +
+

Introduction

+

+This document describes how to fetch and install Pmw, and how to run +the demonstrations and tests. + +

+ +
+

Requirements

+

+Pmw.1.2 requires the _tkinter and Tkinter modules. It works +with python versions 1.5.2 and greater (tested up to 2.2.1) and Tk +versions 8.0 and greater (tested up to 8.3.2). + +

+ +

+If the BLT extension to Tk is present, Pmw will use the BLT busy +command during modal dialogs to display a clock cursor. Also, the +Pmw.Blt interface to the BLT busy, graph, stripchart, tabset and +vector commands will be available. BLT versions 2.4i and greater are +supported (tested up to 2.4u). You can find BLT at +http://www.tcltk.com/blt/. + +

+ +
+

Distribution and installation

+

+Releases of the Pmw distribution are available via http from +http://download.sourceforge.net/pmw/. This release is available +as +Pmw.1.2.tar.gz, released on 5 August 2003. +This is a compressed tar file. Under Linux, Unix, etc, you will need to +unpack it using tar and you may also need to use +gzip or gunzip to uncompress it. +Under Microsoft Windows, you will need a program such as WinZip (http://www.winzip.com) that can +unpack the gzipped tar files. You may need to change the suffix of +the file to .tgz for WinZip to recognise it. + +

+ +

+ +This will unpack into a directory named Pmw. You now need to put this +directory somewhere python can find it, preferably in one of the +standard places, such as in the site-packages directory +(eg: /usr/lib/python2.2/site-packages/Pmw) or the +sys.prefix directory (eg: C:\Program +Files\Python\Pmw or /usr/lib/python2.2). + +

+ +

+ +For example, under Unix, assuming you have placed the tar file in the +/tmp directory, you can simply run the following +commands: + +

+ +
+
+
+cd /usr/lib/python2.2/site-packages
+gunzip /tmp/Pmw.1.2.tar.gz (or gzip -d /tmp/Pmw.1.2.tar.gz)
+tar xvf /tmp/Pmw.1.2.tar
+
+
+
+ +

+ +If you do not have write permission for these standard directories, +place the Pmw +directory somewhere on your PYTHONPATH or +sys.path. If this is not possible, place the Pmw +directory somewhere else and add the parent directory to your +PYTHONPATH or sys.path. + +

+ +

+ +If you have previously installed Pmw version 0.6 or later, then the +new version can share the same Pmw directory as the +previous versions. You will need to perform the tar +extraction in the directory containing (that is, the parent directory +of) the existing Pmw directory. By default, your +applications will use the most recent version of Pmw. If required, +the function Pmw.setversion() can be used to specify a +version to be used. See the reference manual for details. If you are +no longer using the older versions, you can safely remove the +corresponding subdirectories from the Pmw directory. + +

+ +

+ +If you need assistance in installing BLT under Unix, please contact me +(gregm@iname.com) and I +will try to help. For other operating systems, such as Microsoft or +Macintosh, you should try asking the python newsgroup. If anyone can +give me a description of how to install BLT under other operating +systems please contribute it and I will place it here. + +

+ +
+

Documentation

+

+The doc directory for each Pmw version contains all the +documentation for that version of Pmw. See the local home page for a complete list of documents. The +files in this directory are also available from the official Pmw home page. + +

+ +

+An excellent tutorial and reference covering the Pmw interface to the +powerful Blt graph widget, "A User's Guide to +Pmw.Blt" written by Bjørn Ove Thue and Hans Petter Langtangen, is +available. You can also download the full +HTML document for local viewing. + +

+
+

Demonstrations and tests

+

+ A good way to get an overview of the functionality provided by Pmw + is to run the demonstrations and tests and look at the demonstration + code. To view a comprehensive demonstration of many of the features + of Pmw run the All.py script, which can be found in the + demos subdirectory of each version of Pmw. +

+ +

+ + You do not have to install Pmw to run the demonstrations and tests, + simply change into the appropriate directory and run the file + All.py. See Demonstrations and tests for more + information about running the demonstrations and tests and how to + create your own. +

+ +

+ +Note that there are some bugs in later versions of BLT (at least 2.4t +and 2.4u) which cause some tests of Pmw.Blt.Graph to crash with +python2.0 under Linux. These tests have been commented out (until BLT +is fixed). + + +

+

Contributions welcome

+ +

+If you create some whiz-bang megawidgets and would like to contribute +them to Pmw, they will be most welcome. You should be able to get +some idea of the coding style used in Pmw code by reading How to build Pmw megawidgets and by looking +at the Pmw library code itself in the lib directory of +each Pmw version. + +

+ +

+If you would like to contribute a megawidget, it would be preferable if it +also came with a simple demonstration and a test script. See Demonstrations and tests for information +about how to create new demonstrations and tests. +

+ +

+Each megawidget should also have a reference manual describing its +options, components and methods. + +

+ + +
+

Generating the documentation

+ +

+The released reference manuals are +automatically generated by merging specially marked-up text with the +output from megawidget query methods, such as +components(), options() and +componentaliases(), and various other introspective +devices. If you are interested to see how the documentation is generated, +you can fetch the marked-up text and the python script to convert the +text to html from + +http://download.sourceforge.net/pmw/Pmw.1.2.docsrc.tar.gz +. Download this +file into the Pmw/Pmw_1_2 directory of the Pmw source +tree. Unzip and untar the file. This will create a +docsrc sub-directory of Pmw/Pmw_1_2. If +you want to keep the documentation which came with the Pmw +distribution, rename the old doc directory. Then change +directory to docsrc and run createmanuals.py. +After printing lots of warnings about documentation that has not been +written yet, this will create a new doc directory +containing all the html documentation. +

+ +

+Here is an example set of commands to unpack the documentation source +and regenerate the documentation, assuming you have downloaded the +source in the Pmw/Pmw_1_2 directory: +

+ +
+
+
+cd Pmw/Pmw_1_2
+gunzip Pmw.1.2.docsrc.tar.gz
+tar xvf Pmw.1.2.docsrc.tar
+mv doc doc.old
+cd docsrc
+./createmanuals.py
+
+
+
+ +

+If running under Unix, you will need to run the +createmanuals.py script with a valid DISPLAY environment +variable, since it creates each megawidget and then queries it for its +options, components, etc. This is because Tk (and hence Tkinter) +requires a connection to an X server to run. + +

+ +
+

Future plans and bugs

+ +

+The todo list contains a long list of of +suggestions, bugs and enhancements for Pmw. If you are interested in +doing any of these, please let the maintainer +(gregm@iname.com) know. +Some of the items in the todo list may be considered bugs. There are +also some other problems due to idiosyncrasies in the implementation +of Tk. + +

+ +
+

Licence

+ +

+The official Pmw licence (see copyright) +basically lets you do anything with Pmw as long as you don't hurt anyone. +There is also another licence, the "Postcard Licence": +

+ +"I'd like to get a postcard from you! I'm interested in who is using +Pmw, where you live and where in the world Pmw is doing it's job" + +

+Please send me an e-mail to +gregm@iname.com +to get my postal address. +

+ +
+

Acknowledgements

+ +

+The initial ideas for Pmw were blatantly stolen from the itcl +extensions +[incr Tk] +by Michael McLennan and +[incr Widgets] +by Mark Ulferts. Several of the megawidgets are direct translations +from the itcl to python. +

+ +

+The base classes and most megawidgets were written by Greg McFarlane +and Peter Munnings. Contributed megawidgets include: Pmw.TimeCounter +by Joe VanAndel, Pmw.Group and an early version of Pmw.NoteBook by Case Roole, +Pmw.ScrolledCanvas, Pmw.ScrolledFrame and another early version of +Pmw.NoteBook by Joe Saltiel +and Pmw.OptionMenu by Roman Sulzhyk. A big thank you to the following +people for their bug reports, fixes, enhancements and suggestions: + +David Ascher, +Robin Becker, +Siggy Brentrup, +Mark Colclough, +Jerome Gay, +Clemens Hintze, +Rob Hooft +Jack Jansen, +Jonathan Kelly, +Magnus Kessler, +Matthias Klose, +Andreas Kostyrka, +Fredrik Lundh, +Magnus Lycka, +Graham Matthews, +Dieter Maurer, +Michael McLay, +Daniel Michelson, +Georg Mischler, +Rob Pearson, +Case Roole, +Joe Saltiel, +Roman Sulzhyk, +Shen Wang, +Chris Wright, + and +Guido van Rossum. + +Special thanks to Case Roole and Michael McLay for help with getting +Pmw to work with python packages and many other nifty features. + +My deepest apologies if I have forgotten anyone. Please let me know. + +

+ +

+The Pmw home page and project site is made available courtesy of +SourceForge. + +

+

+ +The current maintainer is Greg McFarlane. I monitor the Pmw +discussion and announcement mailing list so please send any +problems, comments, suggestions or enhancements to the list. You may +also contact me directly at gregm@iname.com. + +

+
+
+ + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/todo.html b/Pmw/Pmw_1_2/doc/todo.html new file mode 100644 index 00000000..9ca6889f --- /dev/null +++ b/Pmw/Pmw_1_2/doc/todo.html @@ -0,0 +1,1111 @@ + + + + + + Pmw todo list + + + + +

Pmw todo list

+ +

+This is a long list of suggestions and enhancements for Pmw. If +you are interested in doing any of these, please let the Pmw maintainer +(gregm@iname.com) know.

+ +

New Pmw megawidgets

+
  • Multicolumn listbox.

    +

    Useful features - smooth scrolling, embedded images, different + fonts and colours, text correctly masked when it is longer than + its column width, interactive resizing of columns.

    + +

    Probably should be implemented as canvas widget rather than by + using multiple frames or multiple listboxes. There would be a + lot of work needed to position all the elements - you can't just + pack or grid them.

    + + +
  • +
  • File dialog.

    + +
  • +
  • Main window class (App class), with menu bar, information line + with status boxes and an about box. (See iwidgets' mainwindow + class for example.) This should handle creation of multiple main + windows, recycling of unused main windows and should exit if + last open main window is closed.

    + +
  • +
  • Searchable text megawidget.

    + +
  • +
  • Tree browser.

    + +
  • +
  • Check out Doug Hellmann's contributed megawidgets at + <http://www.mindspring.com/~doughellmann/Projects/PmwContribD> or + <http://members.home.net/doughellmann/PmwContribD/> + and integrate into Pmw.

    + +
+ +

Changes to current megawidgets

+

MegaToplevel

+
  • Modify activate() geometry argument to allow window positioning + relative to the pointer, another window or the screen and + allow the centering of the window relative to the + positioning point or by a specified offset. Also add the + ability to position the window so that the mouse is over a + particular widget in the toplevel.

    +

    Should handle all combinations of

    +
     when (always/first)
    + where (center/geometry/mouse)
    + parent (screen/window)
    +
    + and None (don't position)
    + + +

    Check Tix4.1.0/library/DialogS.tcl center method for how to + center over another window

    + +

    Check iwidget's shell.itk for code to center widget over + screen or another widget.

    + +

    See Pmw.Balloon code for how to position over pointer.

    + +

    Tcl code to center over another (parent) window:

    +
     # center client relative to master (default xoff, yoff = -1)
    + set geomaster [split [wm geometry $master] "x+"]
    + set geoclient [split [wm geometry $client] "x+"]
    +
    + if {$xoff == -1} {
    +   set xoff [expr (
    +     ([lindex $geomaster 0] - [lindex $geoclient 0]) / 2)]
    + }
    + set newxpos [expr [lindex $geomaster 2] + $xoff]
    +
    + if {$yoff == -1} {
    +   set yoff [expr (
    +     ([lindex $geomaster 1] - [lindex $geoclient 1]) / 2)]
    + }
    + set newypos [expr [lindex $geomaster 3] + $yoff]
    +
    + wm geometry $client +$newxpos+$newypos
    + + +

    More tcl code to center dialog over another (parent) window:

    +
     (args: parent dlg)
    + # First, display the dialog offscreen to get dimensions.
    + set screenW [winfo screenwidth $parent]
    + set screenH [winfo screenheight $parent]
    + set w [expr $screenW + 1]
    + wm geometry $dlg +$w+0
    + update
    +
    + # Get relative center of parent. 
    + set w [winfo width $parent]
    + set h [winfo height $parent]
    + set w [expr $w/2]
    + set h [expr $h/2]
    +
    + # Get and add screen offset of parent.
    + set w [expr $w + [winfo rootx $parent]]
    + set h [expr $h + [winfo rooty $parent]]
    +
    + # Get dimensions of dialog.
    + set dlgW [winfo width $dlg]
    + set dlgH [winfo height $dlg]
    +
    + # Make adjustments for actual dimensions of dialog.
    + set w [expr $w - $dlgW / 2]
    + set h [expr $h - $dlgH / 2]
    +
    + # Let's keep the entire dialog onscreen at all times.
    + # Center in screen if things are awry.
    + set recenter 0
    + if { $w < 0 } { set recenter 1 }
    + if { $h < 0 } { set recenter 1 }
    + if { [expr $w + $dlgW] > $screenW } { set recenter 1 }
    + if { [expr $h + $dlgH] > $screenH } { set recenter 1 }
    + if { $recenter } {
    +   set w [expr ($screenW -$dlgW) / 2]
    +   set h [expr ($screenH - $dlgH) / 2]
    + }
    +
    + wm geometry $dlg +$w+$h
    + + + +
  • +
  • Add geometry argument to show() (same as activate() above).

    + +
+ +

Dialog

+
  • Add label (header?) to Dialog class. May not be necessary, or + too complicated.

    + +
+ +

ButtonBox

+
  • When a horizontal ButtonBox is stretched, the left button + stays anchored to the left edge and there is too much space + between the last button and the right edge.

    + +
  • +
  • Add an option to either evenly space the buttons across the + button box, or to keep them together and justify them to the + left, right or center. Check that deleting buttons works + correctly.

    + +
+ +

ComboBox

+
  • Remove arrowrelief option from ComboBox and do what counter + does: gets value of arrow's relief just before sinking it, + then restores it later.

    + +
  • +
  • Change bindings: remove all bindings from arrow key and remove + arrow key from <tab> focus sequence; only implement these + bindings on the entry widget:

    +
     Up    popup dropdown list, scroll up if already displayed
    + Down  popup dropdown list, scroll down if already displayed
    + Esc   popdown dropdown list, return entry to previous value
    + Enter popdown dropdown list, execute current selection
    + +

    Remove bindings from listbox and scrollbar(s), so that all + bindings are via the entry widget?

    + + +
  • +
  • When entering keys when list is displayed, scroll list to + first entry beginning with entered keys. If no match, + scroll list to top.

    + +
  • +
  • Remove many of the arrow bindings from Pmw.ComboBox - there + are just too many key bindings on the arrow button. There + is no need for it to respond to keys such as the up/down + keys when the adjacent Entry widget already does so. I + propose to remove all Pmw.ComboBox arrow button key bindings + except for <space>, which can be used to bring up the + dropdown list. The Entry widget behaviour would remain + unchanged: when it has focus, you can use the up/down keys + to go to the next/previous entries and then use <Return> to + invoke the selection command.

    +

    Alternatively, make the bindings the same as the MS-Windows + combobox. (Use the url entry field in Navigator or IE as an + example of MS-Windows behaviour). These have been reported + to be:

    +
    • All mouse actions are exclusively triggered by the left + button.

      + +
    • +
    • Right button displays "Direkthilfe" on my german system + ("Direct Help"). This is a floating button, that + triggers display of a tool tip like the |?| button that + appears next to the |x| at the right end of the title + bar of some native windows dialogs.

      + +
    • +
    • The arrow is very slim (acutally flat: width/height is + about 2/1)

      + +
    • +
    • Entry and popup have the same color ("window color")

      + +
    • +
    • The popup has a 1 pixel dark border, no spacing between + popup and scrollbar.

      + +
    • +
    • If the box has the focus, the full entry is displayed in + "selected" style.

      + +
    • +
    • If the box has the focus, up and left keys rotate items + up, down and right keys rotate items down, all with + immediate effect.

      + +
    • +
    • If the box has the focus, keys a-z (not case sensitive) + rotate through the items with same first character, with + immediate effect.

      + +
    • +
    • No separate focus for the arrowbutton

      + +
    • +
    • Discussing how the combobox behaves with arrow keys when + it has the focus: "The concept is almost identical to + what you already have, just gives more visual feedback. + In your current implementation you allow to rotate + through the values with the up and down arrow keys, + showing the strings in the entryfield, and accepting the + values when the user presses the spacebar (hmmm, how can + I exit this without moving back to the original value + manually?). On Windows, the choice is not shown in the + entryfield, but the popup opens when you press the up or + down arrow keys, as if you clicked on the arrowbutton, + and you then navigate the values in the listbox. This + avoids the display of not finally selected values in the + entryfield and is a lot more obvious and less confusing. + The current behaviour certainly confused me, which is + why I first proposed the changes to the moveup/down + methods." (Georg Mischler)

      + +
    + +

    Also, check bindings on other megawidgets for consistency.

    + + +
  • +
  • Modify Pmw.ComboBox so that the width of the entry widget is + forced to be the same as the width of the dropdown listbox. + If the "width" option to the standard listbox is 0, Tk sets + the requested width of the listbox to be just large enough + to hold the widest element in the listbox. Using this + option, I can see that listbox.winfo_reqwidth() is changing + as I insert items into an unmapped listbox. The question + is, how do I get notified of these events so that I can set + the width of the entry?

    +

    The problem is that the listbox is in another toplevel which + has not yet been displayed, so I can't bind to <Configure> + to determine its width.

    + +

    One suggestion is to override the insert and delete methods + of the Listbox class. The problem with this is what if the + font changed, or the borderwidth, etc? You would need to + override and check many more methods.

    + + +
  • +
  • Add ability to tearoff dropdown list (suggested by Dean N. + Williams).

    + +
  • +
  • Should be able to disable/enable arrow button.

    + +
+ +

Counter

+
  • Add option for different increment/decrement behaviour. For + example, assuming increment is 1:

    +
    1. Current behaviour - move to the next multiple of the + increment, eg: 1.0 -> 2.0, 1.234 -> 2.0

      + +
    2. +
    3. Add or subtract the increment to whatever is displayed, + eg: 1.0 -> 2.0, 1.234 -> 2.234

      + +
    4. +
    5. Move to the next multiple of the increment, offset by some value. + eg: (if offset is 0.5) 0.5 -> 1.5, 1.234 -> 1.5, 1.678 -> 2.5

      + +
    + +
  • +
  • Add wrap option (to wrap around at limits) (then don't need + time24 arg to 'time' datatype).

    + +
  • +
  • Add a state option to disable Counter.

    + +
  • +
  • Add option to Counter to allow the buttons to be on the same + side, one on top of the other, like Tix, Itcl, Motif, + Windows 95, etc. There should probably also be an option to + lay the current large buttons on the same side of the entry + field, next to each other.

    + +
  • +
  • Redo TimeCounter using vertical Counter, add limitcommand + option to Counter to allow overflow from seconds to minutes + to hours

    + +
+ +

Arrowed megawidgets (Counter, ComboBox, TimeCounter)

+
  • Potential construction speed up if Canvas arrows are replaced + by Label with Bitmap or BitmapImage. The hard part would be + to make the bitmap change size depending on size of Label.

    + +
  • +
  • Pmw.drawarrow should draw arrows which look like Tk cascade + menu arrows.

    + +
+ +

EntryField

+
  • Can it be modified to change all entered characters to upper + or lower case automatically? Or first-upper or + first-of-each-word-upper?

    + +
  • +
  • If the validity of the currently displayed text is ERROR, + allow any changes, even those which result in invalid text. + This is useful when invalid data has been given to the + value option and the user is trying to correct it.

    + +
+ +

LabeledWidget

+
  • Add tix-style border.

    + +
+ +

MenuBar

+
  • Maybe Pmw.MenuBar should also have (optional) balloon help + for menu items as well as menu buttons. I am not sure + whether users would find this useful.

    + +
  • +
  • The status help hints do not appear when using F10/arrow + keys.

    + +
  • +
  • Look at the Tk8.0 menu demo and check the help bindings for + ideas, in particular, how can you get help when using + keyboard bindings.

    + +
  • +
  • Check the new menu features in Tk8.0 for creating "native" + menu bars and the special ".help" menu.

    + +
  • +
  • Add index() method.

    + +
  • +
  • Add a 'position' option to addmenu and deletemenu methods. + This option should accept an index number, a menuName or + Pmw.END.

    + +
  • +
  • Look at itcl menubar for ideas.

    + +
+ +

Balloon

+
  • Positioning of the balloon with respect to the target + widget or canvas item: There are a number of ways that + Pmw.Balloon could be improved. For example, currently the + the top left corner of the balloon is positioned relative to + the bottom left corner of the target, offset by the + [xy]offset options. These options apply to all targets - + they can not be set differently for different targets.

    +

    To make it more configurable, the user should be able to + specify, for each target:

    +
    • the base position in the target relative to which the + balloon should be placed (n, s, e, w, nw, sw, ne, se, c) + (Currently sw)

      + +
    • +
    • the x and y offsets (Default (20, 1))

      + +
    • +
    • the position in the balloon that should be placed at the + offset position (n, s, e, w, nw, sw, ne, se, c) + (Currently nw)

      +

      Note, if this is anything other than nw, + update_idletasks() will need to be called to get the + size of the balloon before it is positioned - there is a + possibility that this may cause weird ugly flashing.

      + + +
    • +
    • whether either the base x or y position should be taken + relative to the current mouse position rather than as + one of the corners of the target. This would be useful + for large targets, such as text widgets, or strange + shaped canvas items. This could be specified using + special base positions, such as (nm, sm, em, wm). For + example, for 'sm', the x base position is the mouse x + position and y base position is the bottom (south) edge + of the target.

      + +
    + +

    The user should be able to specify global defaults for all + of these, as well as be able to override them for each + target. The Pmw.Balloon options and their defaults could + be:

    +
     basepoint   sw        # Position on target.
    + anchor      nw        # Position on the balloon
    + xoffset     20        # x distance between basepoint and anchor
    + yoffset     1         # y distance between basepoint and anchor
    + + +

    To be able to override these, the bind() and tagbind() + methods would have to accept these as additional arguments. + Each would default to None, in which case the default values + at the time the balloon is deiconified would be used.

    + +

    I'm not sure about how to handle the case when the balloon + is configured to come up under the mouse. When this happens + the balloon flashes on and off continuously. This can + happen now if you set the yoffset to a negative number. + Should the balloon widget detect this and do something about + it?

    + + +
  • +
  • Add showballoon(x, y, text) method to Balloon and use in + balloon help for a listbox:

    +

    On 3 Dec, Michael Lackhoff wrote:

    + +
     And another question:
    + Is it possible to create a balloon-help for the entries
    + in the listbox?  Not all the information is in the
    + listbox and it would be nice if a balloon help could
    + give addtional information.
    + +

    Rather than popup a balloon help window as the mouse moves + over items in the listbox, I think it would be better if it + pops up after you clicked on an item (or a short time + afterwards). Pmw.Balloon displays the balloon help a short + time after the mouse enters a widget, so is not directly + usable in this case. However, a method could be added to + Pmw.Balloon to request it to popup the balloon at a + particular x,y position. This method could be called from + the listbox_focus method above. Something like:

    +
     def listbox_focus(self, event):
    +     self.indexlist.component('listbox').focus_set()
    + +
         text = self.indexlist.getcurselection()
    +     # expand text to whatever you want:
    +     text = 'This is ' + text
    +     self.balloon.showballoon(x, y, text)
    + + +

    The Pmw.Balloon showballoon() method would have to set a + timer which sometime later calls another method which + displays the text. You would also need to bind + <ButtonRelease-1> to a hideballoon() method which withdraws + the popup.

    + + +
  • +
  • The balloon can be displayed off-screen if the window is + near the edge of the screen. Add a fix so that the balloon + always stays on the screen (but does not popup under the + mouse, otherwise it will immediately pop down).

    + +
  • +
  • Add a fix so that the balloon does not disappear if the + mouse enters it. Could do this by setting a short timer on + the Leave event before withdrawing the balloon and if there + is an Enter event on the balloon itself, do not withdraw it.

    + +
  • +
  • For tagged items in text widgets, the balloon is placed + relative to the character in the tagged item closest to the + mouse. This is not consistent: in the other cases + (including canvas), the balloon is placed relative to the + bottom left corner of the widget or canvas item. This + should also be the case for text items.

    + +
  • +
  • Is the new (in Tk8) "<<MenuSelect>>" event useful for + balloon and/or status help.

    + +
+ +

MessageBar

+
  • Finish logmessage functionality.

    + +
  • +
  • Add colours and fonts to MessageBar message types. For + example, systemerror message types could have bold font on a + red background.

    + +
  • +
  • Add message logging history view (like the ddd debugger).

    + +
+ +

NoteBook

+
  • Notebook should recalculate layout if the requested size of a tab + changes (eg font size, text, etc).

    + +
  • +
  • The tabpos option should accept s, e and w as well as n.

    + +
  • +
  • Possible new options (borrowed from iwidgets):

    +
    • equaltabs

      +

      If set to true, causes horizontal tabs to be equal in + in width and vertical tabs to equal in height.

      + +

      Specifies whether to force tabs to be equal sized or + not. A value of true means constrain tabs to be equal + sized. A value of false allows each tab to size based + on the text label size. The value may have any of the + forms accepted by the Tcl_GetBoolean, such as true, + false, 0, 1, yes, or no.

      + +

      For horizontally positioned tabs (tabpos is either s or + n), true forces all tabs to be equal width (the width + being equal to the longest label plus any padX speci- + fied). Horizontal tabs are always equal in height.

      + +

      For vertically positioned tabs (tabpos is either w or + e), true forces all tabs to be equal height (the height + being equal to the height of the label with the largest + font). Vertically oriented tabs are always equal in + width.

      + +

      Could have a special value which sets equal sized and + also forces tabs to completely fill notebook width + (apparently like + Windows).

      + + +
    • +
    • tabgap

      +

      Specifies the amount of pixel space to place between + each tab. Value may be any pixel offset value. In addi- + tion, a special keyword overlap can be used as the + value to achieve a standard overlap of tabs. This value + may have any of the forms acceptable to Tk_GetPixels.

      + + +
    • +
    • raiseselect

      +

      Sets whether to raise selected tabs slightly (2 pixels).

      + +

      Specifes whether to slightly raise the selected tab + from the rest of the tabs. The selected tab is drawn 2 + pixels closer to the outside of the tabnotebook than + the unselected tabs. A value of true says to raise + selected tabs, a value of false turns this feature off. + The default is false. The value may have any of the + forms accepted by the Tcl_GetBoolean, such as true, + false, 0, 1, yes, or no.

      + + +
    • +
    • bevelamount

      +

      Specifies pixel size of tab corners. 0 means no corners.

      + + +
    + +
  • +
  • There should be a way to temporarily hide a page, without + deleting it (like pack_forget). (Suggested by Michel Sanner)

    + +
+ +

OptionMenu

+
  • Should accept focus and obey up and down arrow keys.

    + +
+ +

PanedWidget

+
  • Add index() method

    + +
  • +
  • Modify all methods so that they accept Pmw.END as a pane + identifier as well as an index or a name.

    + +
  • +
  • Check iwidgets pane and panedwindow classes.

    + +
+ +

RadioSelect

+
  • Add insert() and delete() methods.

    + +
  • +
  • The index method should have forInsert argument.

    + +
  • +
  • Add Pmw.SELECT to index() method. For single selectmode + this returns an integer, for multiple selectmode this + returns a list of integers.

    + +
  • +
  • Add option to set background color on selected buttons. + Maybe should also be able set selected foreground as well. + Any others?

    + +
+ +

LogicalFont

+
  • Add boldFixed fonts,

    + +
  • +
  • Search for closest size font if no exact match.

    + +
  • +
  • Maybe replace with Tk8.0 font mechanism.

    + +
  • +
  • Can the Tk8.0 font measuring functionality be used in Pmw somehow?

    + +
+ +

Scrolled widgets

+
  • Can some common scrolling methods be factored out, either as + a base class, "ScrolledMixin" mixin class or as helper functions? + Candidate methods: constructor, destroy, interior, _hscrollMode, + _vscrollMode, _configureScrollCommands, _scrollXNow, _scrollYNow, + _scrollBothLater, _scrollBothNow, _toggleHorizScrollbar, + _toggleVertScrollbar.

    + +
  • +
  • ScrolledField should have optional arrow buttons, so that it + can still be scrolled even if the mouse does not have a + middle button.

    + +
+ +

Miscellaneous

+
  • Add a button to the Pmw "Stack trace window" which + optionally removes all grabs:

    +

    I normally interact with the "Stack trace window" + immediately, and dismiss it afterwards. In many cases + where a bug appears like this, the rest of the application + is still functional (many of the problems appearing at + this stage of development of my application are unforeseen + exceptions communicating with a robot on the other end of + a socket, not affecting the GUI per se). For that reason + I'd prefer if the "stack trace window" would push another + grab on the grab stack (if any grabs are active at the + moment the exception occurs). Could the window have an + extra "Terminate application" option for this case?

    + + +
  • +
  • need to handle component option queries in configure():

    +
     foo = Pmw.AboutDialog(applicationname = 'abc XYZ')
    + foo.component('message').configure('text')    - works
    + foo.cget('message_text')                      - works
    + foo.configure('message_text')                 - doesn't
    + + +
  • +
  • Implement bindings (ComboBox, etc) via a dictionary lookup, + to allow people to invent new bindings, such as for + handicapped users. (Suggested by Michael McLay)

    + +
  • +
  • Modify bundlepmw.py so that it checks Pmw.def to see that no + files have been missed.

    + +
  • +
  • Potential cheap speedup by adding this to each module, or + inside functions if it has a loop containing calls to + builtins:

    +
     from __builtin__ import *
    + + +
  • +
  • Look at how update_idletasks and after_* are used in Pmw - + are they consistent? could it be improved? What are the + problems of using these on other bits of an application + (such as when the size of the toplevel is being determined + for the window manager).

    + +
  • +
  • If lots of errors occur (such as in a fast time callback) + the error window may not appear, since Tk will wait until it + is idle - which may never occur. The solution is to call + update_idletask when updating the error window, but only + after a short time has passed. This will provide better + user response. However, it may not be possible to do this + if some python interpretes (omppython, for example) do not + handle calls to update_idletasks at certain times.

    + +
  • +
  • In the Pmw FAQ, in the "Why don't Pmw megawidgets have a + 'state' option?" section, it mentions several Pmw + megawidgets that can not be disabled. Fix them.

    + +
  • +
  • Add RCSID version string to all files.

    + +
  • +
  • When raising exceptions use the third argument to raise:

    +
     raise SimulationException, msg, sys.exc_info()[2]
    + + +
  • +
  • When update_idletasks is called all pending changes are + flushed to the window system server. However, it may take + some time for the server to display the changes. If it is + required that the display be up-to-date, update_idletasks + should be followed by a call that blocks until processed by + the server and a reply received. This may be useful in + Pmw.busycallback to ensure the busy cursor remains visible + until the display is actually modified.

    + +
  • +
  • There is a small bug which appears only with Tk8.0 (the bug + is not apparent with Tk4.2). If a dialog is activated and + pops up directly over the cursor and the dialog has a + default button, then pressing the <strong>Return</strong> + key will not invoke the default button. If you move the + mouse out of and then back into the dialog, pressing the + <strong>Return</strong> key will work. This behaviour has + been noticed in Tcl-only programs, so it is probably a bug + in Tk. (Tested on Solaris.)

    + +
  • +
  • Modify PmwBlt.py to use blt2.4 instead of blt8.0.unoff. + Nick Belshaw <nickb@earth.ox.ac.uk> is looking at wrapping + the new BLT StripChart and TabSet into Pmw.

    + +
  • +
  • Perhaps Pmw should have its own exception defined, like + TkInters's TclError, perhaps called PmwError.

    + +
  • +
  • This one is caused by a bug in the implementation of Tcl/Tk + for Microsoft Windows NT (and maybe other Microsoft + products). Mouse release events can get lost if the + grab_set and grab_release commands are used and the mouse + goes outside of the window while the mouse button is down. + This can occur while Pmw modal dialogs are active. Below + is some Tkinter-only code which demonstrates the problem. + Maybe there is a work around.

    +
     # Test script to demonstrate bug in Tk
    + #implementation of grab under NT.
    +                                 
    + # Click on "Dialog" to bring up the modal
    + # dialog window.  Then button down on the scale,
    + # move the mouse outside the window,
    + # then button up.  The scale slider will still
    + # be sunken and clicks on the "OK" button
    + # will be ineffective.
    + 
    + import Tkinter
    + 
    + def activate():
    +     waitVar.set(0)
    +     toplevel.deiconify()
    +     toplevel.wait_visibility()
    +     toplevel.grab_set()        # Problem here
    +     toplevel.focus_set()
    +     toplevel.wait_variable(waitVar)
    + 
    + def deactivate():
    +     toplevel.withdraw()
    +     toplevel.grab_release()    # and here
    +     waitVar.set(1)
    + 
    + root = Tkinter.Tk()
    + toplevel = Tkinter.Toplevel()
    + waitVar = Tkinter.IntVar()
    + toplevel.withdraw()
    + scale = Tkinter.Scale(toplevel, orient='horizontal', length=200)
    + scale.pack()
    + button = Tkinter.Button(toplevel, text='OK', command=deactivate)
    + button.pack()
    + 
    + button = Tkinter.Button(text='Dialog', command=activate)
    + button.pack()
    + button = Tkinter.Button(text='Exit', command=root.destroy)
    + button.pack()
    + 
    + root.mainloop()
    + + +
+ + +

Documentation

+
  • Document how to get Pmw working on a Mac, for example:

    +
    • Unzip and untar

      +

      This depends on what you use to unpack the tar file. If + you use (macgzip and) SunTar you have to tell it that files + with ".py" extensions are text files (in the + preferences/file type section). If you use stuffit + expander: this can be made to do the conversion + correctly, but it could be that this only works if you set + the .py extension correctly in Internet Config.

      + +
      • Where do you untar Pmw?

        + +
      • +
      • How do you get line terminators correct (carriage + return/line feed)?

        + +
      • +
      • Is there any problem with file name case? (mixed + upper/lower case)

        + +
      • +
      • Is there any problem with file name length?

        + +
      +

      (Joseph Saltiel says: It was the same type of operation + as in Windows/Unix. Run a program that unzips it and + untars it. It seems to get case and length right on its + own.)

      + + +
    • +
    • Let python know where Pmw is

      +
      • If Pmw is in its own folder you will have to add the + parent of that folder to the sys paths in Edit + PythonPaths. If it is in the Python home folder, you + do not need to do this.

        + +
      • +
      • Make sure that the Pmw folder is called "Pmw" and not + something else. Since Pmw is a package, python expects + to find a "Pmw" folder somewhere in sys.path.

        + +
      +

      (Joseph Saltiel says: With the Python distribution on the + Mac there is an application called editPythonPrefs, when + you run it it gives you a list of a paths. These paths + are similiar to the PYTHONPATH variable. I just added the + path to Pmw at the bottom of this list.)

      + + +
    + +
  • +
  • Document general ideas about building guis, eg:

    +

    When I write gui applications, I usually defer creation of windows + as much as possible - this means that the application starts up + quickly because it usually only has to create the main window. + Whenever another window is required for the first time, it is + created then. When the user has finished with the window, the + window is withdrawn, not deleted, so that next time it is required + it much faster to come up.

    + +

    In summary - don't create a window until you need and + don't destroy a window if you may want it again.

    + +

    The amount of memory required to keep the windows should not be + very much - except for very long running programs where the user + may create thousands of different windows.

    + + +
  • +
  • Add class hierarchy diagram to documentation:

    +
     MegaArchetype
    +     MegaToplevel
    +        etc
    +     MegaWidget
    +        etc
    + + +
  • +
  • Add to doco something like: "Another way to extend a Pmw + megawidget is to specify a non-default type for one of the + components. For example text_pytype = FontText."

    + +
  • +
  • Document pyclass and pyclass = None (options for null components + are ignored; the only time this can be used is with the + Group's tag component - all + other's use the component widget in some way)

    + +
  • +
  • Create index of all Pmw methods, functions, options, components.

    + +
  • +
  • Add description of how to run the Pmw demos without installing.

    + +
  • +
  • Add description of how to install Pmw.

    + +
  • +
  • Describe grid structure of megawidgets, so that it is possible + to extend megawidgets by adding new widgets into the interior + (hence avoiding a childsite in most megawidgets)

    + +
  • +
  • Document error display and difference between callback and + binding error reports.

    + +
  • +
  • Document difference between 'Helvetica 12' and 'Helvetica size: 12' + in logicalfont.

    + +
  • +
  • Add to howtouse, to describe using the option database to set + options for a specific megawidget:

    +
     import Pmw
    + root = Pmw.initialise(useTkOptionDb = 1)
    + root.option_add('*entryfield24*Label.text', 'German')
    + e = Pmw.EntryField(hull_name = 'entryfield24', labelpos = 'w')
    + e.pack()
    + root.update()
    + + +
  • +
  • Also document hull_name and hull_class.

    + +
  • +
  • Finish FAQ, ReleaseProcedure and StructuredText test.

    + +
  • +
  • Put html through gifwizard and html lint.

    +
     http://www.cen.uiuc.edu/cgi-bin/weblint
    + (eg: http://www.cre.canon.co.uk/~neilb/weblint/manpage.html)
    + + +
  • +
  • Delete comments from source if they have been added to docs + (should not have two copies of anything).

    + +
  • +
  • Need to document non-standard initial values for component + options, such as border in ButtonBox and Dialog's childsite.

    + +
  • +
  • Docs should have DEFAULT BINDINGS section (like iwidget combobox).

    + +
  • +
  • Promote home page:

    +
     http://www.geocities.com/homestead/promote.html
    + http://www.submit-it.com/subopt.htm, etc
    + + +
  • +
  • Create man pages as well as html (modify createmanuals to produce both).

    + +
  • +
  • Maybe something with html frames like: itcl2.2/html/index.html

    + +
  • +
  • Add to starting.html a note that Pmw is a python "package" and add + a pointer to python documentation on packages.

    + +
  • +
  • Document scrolled widget implementations, explaining why they + are all slightly different (because the underlying widgets which + are being scrolled have different behaviors).

    + +
  • +
  • Make copyright clearer. Maybe borrow python's?

    + +
+ +

Demos

+
  • Check for missing demos.

    + +
  • +
  • In all demos can move the three lines beginning with "Import Pmw + from the sibling directory", to inside "if __name__" clause. + Also, "sibling directory" is now incorrect. Also, add note that + this is only necessary when running demos without installing Pmw.

    + +
  • +
  • Change demo/All.py so that it displays the traceback if it + cannot load or run a demo (easier for users to report errors).

    + +
  • +
  • Add option to demo/All.py: "Display demos in separate window" + to allow resizing of sub-demos

    + +
  • +
  • TimeCounter and Spectrum demos beep when they come up, using:

    +
     root.option_add('*EntryField*value', 'VALUE')
    + + +
  • +
  • In demos, add title = 'blah' to top of file and replace + root.title(..) with root.title(title) at bottom.

    + +
  • +
  • Add comprehensive speed test demo which creates one or more of + each (common) megawidget. Remove old SpeedTest demo.

    + +
  • +
  • Check demos work when called from ptui. (Changes have to do + with calling compile/exec where __name__ is not the name of the + All.py script, but is '__builtin__')

    + +
  • +
  • PromptDialog demo should not remember password.

    + +
  • +
  • Finish Counter, Radioselect demos.

    + +
  • +
  • Modify the All demo so that you can reload a demo module.

    + +
  • +
  • The syntax-coloured code viewer looks strange on Microsoft NT, + because the size of the fonts differ. Check out Guido's + idle-0.1 text colouring for Pmw code viewer.

    + +
  • +
  • Document restrictions on adding bindings to a megawidget: you + probably need to bind to components of the megawidget and also + check that you are not destroying bindings set up by the + megawidget itself.

    + +
  • +
  • Add a demo that demonstrates setting the color scheme at run time.

    + +
+ +

Tests

+
  • Check for missing tests, such as TimeCounter, RadioSelect, + SelectionDialog, MessageBar, MenuBar, ComboBoxDialog, Balloon.

    + +
  • +
  • Create test for useTkOptionDb option to Pmw.initialise().

    + +
  • +
  • Check that destroyed widgets' python classes are garbage + collected (add test and/or demo).

    + +
  • +
  • Add tests for changecolor, setscheme, etc.

    + +
  • +
  • Need Resources test.

    + +
  • +
  • Create tests for deriving from Pmw classes (eg ComboBox).

    + +
+ +

Ideas

+
  • Add more Tix (www.xpi.com/tix/screenshot.html) and iwidgets widgets.

    + +
  • +
  • Look at spinner.itk for how to do vertical orientation on + same side for Counter.

    + +
  • +
  • Investigate these new features in Tk8.0 and see if they could be + used in Pmw:

    +
     embedded images in text widgets
    + destroy command ignores windows that don't exist
    +
    + + +
+ + + +

+ +

+ + + +

+ Pmw 1.2 - + 5 Aug 2003 + - Home + +

+
+ + + + diff --git a/Pmw/Pmw_1_2/doc/transdove.gif b/Pmw/Pmw_1_2/doc/transdove.gif new file mode 100644 index 00000000..a9d83cdc Binary files /dev/null and b/Pmw/Pmw_1_2/doc/transdove.gif differ diff --git a/Pmw/Pmw_1_2/lib/Pmw.def b/Pmw/Pmw_1_2/lib/Pmw.def new file mode 100644 index 00000000..5965c118 --- /dev/null +++ b/Pmw/Pmw_1_2/lib/Pmw.def @@ -0,0 +1,58 @@ +# [Emacs: -*- python -*-] +# --- This is the Pmw definition file --- +# +# It is invoked by the Pmw dynamic loader in Pmw.__init__. +# +# widgets : tuple with the names of those widget classes that are +# stacked in a module of the same name. +# widgetclasses : dictionary from names of widget classes to module names. +# functions : dictionary from function names to modules names. +# modules : tuple of module names that don't contain widget classes +# of the same name. +# + +# Widgets whose name is the same as its module. +_widgets = ( + 'AboutDialog', 'Balloon', 'ButtonBox', 'ComboBox', + 'ComboBoxDialog', 'Counter', 'CounterDialog', 'Dialog', + 'EntryField', 'Group', 'HistoryText', 'LabeledWidget', + 'MainMenuBar', 'MenuBar', 'MessageBar', + 'MessageDialog', 'NoteBook', 'OptionMenu', 'PanedWidget', + 'PromptDialog', 'RadioSelect', 'ScrolledCanvas', 'ScrolledField', + 'ScrolledFrame', 'ScrolledListBox', 'ScrolledText', 'SelectionDialog', + 'TextDialog', 'TimeCounter', +) + +# Widgets whose name is not the same as its module. +_extraWidgets = { +} + +_functions = { + 'logicalfont' : 'LogicalFont', + 'logicalfontnames' : 'LogicalFont', + 'aboutversion' : 'AboutDialog', + 'aboutcopyright' : 'AboutDialog', + 'aboutcontact' : 'AboutDialog', + 'datestringtojdn' : 'TimeFuncs', + 'timestringtoseconds' : 'TimeFuncs', + 'setyearpivot' : 'TimeFuncs', + 'ymdtojdn' : 'TimeFuncs', + 'jdntoymd' : 'TimeFuncs', + 'stringtoreal' : 'TimeFuncs', + 'aligngrouptags' : 'Group', + 'OK' : 'EntryField', + 'ERROR' : 'EntryField', + 'PARTIAL' : 'EntryField', + 'numericvalidator' : 'EntryField', + 'integervalidator' : 'EntryField', + 'hexadecimalvalidator' : 'EntryField', + 'realvalidator' : 'EntryField', + 'alphabeticvalidator' : 'EntryField', + 'alphanumericvalidator' : 'EntryField', + 'timevalidator' : 'EntryField', + 'datevalidator' : 'EntryField', +} + +_modules = ( + 'Color', 'Blt', +) diff --git a/Pmw/Pmw_1_2/lib/PmwAboutDialog.py b/Pmw/Pmw_1_2/lib/PmwAboutDialog.py new file mode 100644 index 00000000..fe78d276 --- /dev/null +++ b/Pmw/Pmw_1_2/lib/PmwAboutDialog.py @@ -0,0 +1,52 @@ +import Pmw + +class AboutDialog(Pmw.MessageDialog): + # Window to display version and contact information. + + # Class members containing resettable 'default' values: + _version = '' + _copyright = '' + _contact = '' + + def __init__(self, parent = None, **kw): + + # Define the megawidget options. + INITOPT = Pmw.INITOPT + optiondefs = ( + ('applicationname', '', INITOPT), + ('iconpos', 'w', None), + ('icon_bitmap', 'info', None), + ('buttons', ('Close',), None), + ('defaultbutton', 0, None), + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MessageDialog.__init__(self, parent) + + applicationname = self['applicationname'] + if not kw.has_key('title'): + self.configure(title = 'About ' + applicationname) + + if not kw.has_key('message_text'): + text = applicationname + '\n\n' + if AboutDialog._version != '': + text = text + 'Version ' + AboutDialog._version + '\n' + if AboutDialog._copyright != '': + text = text + AboutDialog._copyright + '\n\n' + if AboutDialog._contact != '': + text = text + AboutDialog._contact + + self.configure(message_text=text) + + # Check keywords and initialise options. + self.initialiseoptions() + +def aboutversion(value): + AboutDialog._version = value + +def aboutcopyright(value): + AboutDialog._copyright = value + +def aboutcontact(value): + AboutDialog._contact = value diff --git a/Pmw/Pmw_1_2/lib/PmwBalloon.py b/Pmw/Pmw_1_2/lib/PmwBalloon.py new file mode 100644 index 00000000..e1f88683 --- /dev/null +++ b/Pmw/Pmw_1_2/lib/PmwBalloon.py @@ -0,0 +1,365 @@ +import os +import string +import Tkinter +import Pmw + +class Balloon(Pmw.MegaToplevel): + def __init__(self, parent = None, **kw): + + # Define the megawidget options. + optiondefs = ( + ('initwait', 500, None), # milliseconds + ('label_background', 'lightyellow', None), + ('label_foreground', 'black', None), + ('label_justify', 'left', None), + ('master', 'parent', None), + ('relmouse', 'none', self._relmouse), + ('state', 'both', self._state), + ('statuscommand', None, None), + ('xoffset', 20, None), # pixels + ('yoffset', 1, None), # pixels + ('hull_highlightthickness', 1, None), + ('hull_highlightbackground', 'black', None), + ) + self.defineoptions(kw, optiondefs) + + # Initialise the base class (after defining the options). + Pmw.MegaToplevel.__init__(self, parent) + + self.withdraw() + self.overrideredirect(1) + + # Create the components. + interior = self.interior() + self._label = self.createcomponent('label', + (), None, + Tkinter.Label, (interior,)) + self._label.pack() + + # The default hull configuration options give a black border + # around the balloon, but avoids a black 'flash' when the + # balloon is deiconified, before the text appears. + if not kw.has_key('hull_background'): + self.configure(hull_background = \ + str(self._label.cget('background'))) + + # Initialise instance variables. + self._timer = None + + # The widget or item that is currently triggering the balloon. + # It is None if the balloon is not being displayed. It is a + # one-tuple if the balloon is being displayed in response to a + # widget binding (value is the widget). It is a two-tuple if + # the balloon is being displayed in response to a canvas or + # text item binding (value is the widget and the item). + self._currentTrigger = None + + # Check keywords and initialise options. + self.initialiseoptions() + + def destroy(self): + if self._timer is not None: + self.after_cancel(self._timer) + self._timer = None + Pmw.MegaToplevel.destroy(self) + + def bind(self, widget, balloonHelp, statusHelp = None): + + # If a previous bind for this widget exists, remove it. + self.unbind(widget) + + if balloonHelp is None and statusHelp is None: + return + + if statusHelp is None: + statusHelp = balloonHelp + enterId = widget.bind('', + lambda event, self = self, w = widget, + sHelp = statusHelp, bHelp = balloonHelp: + self._enter(event, w, sHelp, bHelp, 0)) + + # Set Motion binding so that if the pointer remains at rest + # within the widget until the status line removes the help and + # then the pointer moves again, then redisplay the help in the + # status line. + # Note: The Motion binding only works for basic widgets, and + # the hull of megawidgets but not for other megawidget components. + motionId = widget.bind('', + lambda event = None, self = self, statusHelp = statusHelp: + self.showstatus(statusHelp)) + + leaveId = widget.bind('', self._leave) + buttonId = widget.bind('', self._buttonpress) + + # Set Destroy binding so that the balloon can be withdrawn and + # the timer can be cancelled if the widget is destroyed. + destroyId = widget.bind('', self._destroy) + + # Use the None item in the widget's private Pmw dictionary to + # store the widget's bind callbacks, for later clean up. + if not hasattr(widget, '_Pmw_BalloonBindIds'): + widget._Pmw_BalloonBindIds = {} + widget._Pmw_BalloonBindIds[None] = \ + (enterId, motionId, leaveId, buttonId, destroyId) + + def unbind(self, widget): + if hasattr(widget, '_Pmw_BalloonBindIds'): + if widget._Pmw_BalloonBindIds.has_key(None): + (enterId, motionId, leaveId, buttonId, destroyId) = \ + widget._Pmw_BalloonBindIds[None] + # Need to pass in old bindings, so that Tkinter can + # delete the commands. Otherwise, memory is leaked. + widget.unbind('', enterId) + widget.unbind('', motionId) + widget.unbind('', leaveId) + widget.unbind('', buttonId) + widget.unbind('', destroyId) + del widget._Pmw_BalloonBindIds[None] + + if self._currentTrigger is not None and len(self._currentTrigger) == 1: + # The balloon is currently being displayed and the current + # trigger is a widget. + triggerWidget = self._currentTrigger[0] + if triggerWidget == widget: + if self._timer is not None: + self.after_cancel(self._timer) + self._timer = None + self.withdraw() + self.clearstatus() + self._currentTrigger = None + + def tagbind(self, widget, tagOrItem, balloonHelp, statusHelp = None): + + # If a previous bind for this widget's tagOrItem exists, remove it. + self.tagunbind(widget, tagOrItem) + + if balloonHelp is None and statusHelp is None: + return + + if statusHelp is None: + statusHelp = balloonHelp + enterId = widget.tag_bind(tagOrItem, '', + lambda event, self = self, w = widget, + sHelp = statusHelp, bHelp = balloonHelp: + self._enter(event, w, sHelp, bHelp, 1)) + motionId = widget.tag_bind(tagOrItem, '', + lambda event = None, self = self, statusHelp = statusHelp: + self.showstatus(statusHelp)) + leaveId = widget.tag_bind(tagOrItem, '', self._leave) + buttonId = widget.tag_bind(tagOrItem, '', self._buttonpress) + + # Use the tagOrItem item in the widget's private Pmw dictionary to + # store the tagOrItem's bind callbacks, for later clean up. + if not hasattr(widget, '_Pmw_BalloonBindIds'): + widget._Pmw_BalloonBindIds = {} + widget._Pmw_BalloonBindIds[tagOrItem] = \ + (enterId, motionId, leaveId, buttonId) + + def tagunbind(self, widget, tagOrItem): + if hasattr(widget, '_Pmw_BalloonBindIds'): + if widget._Pmw_BalloonBindIds.has_key(tagOrItem): + (enterId, motionId, leaveId, buttonId) = \ + widget._Pmw_BalloonBindIds[tagOrItem] + widget.tag_unbind(tagOrItem, '', enterId) + widget.tag_unbind(tagOrItem, '', motionId) + widget.tag_unbind(tagOrItem, '', leaveId) + widget.tag_unbind(tagOrItem, '', buttonId) + del widget._Pmw_BalloonBindIds[tagOrItem] + + if self._currentTrigger is None: + # The balloon is not currently being displayed. + return + + if len(self._currentTrigger) == 1: + # The current trigger is a widget. + return + + if len(self._currentTrigger) == 2: + # The current trigger is a canvas item. + (triggerWidget, triggerItem) = self._currentTrigger + if triggerWidget == widget and triggerItem == tagOrItem: + if self._timer is not None: + self.after_cancel(self._timer) + self._timer = None + self.withdraw() + self.clearstatus() + self._currentTrigger = None + else: # The current trigger is a text item. + (triggerWidget, x, y) = self._currentTrigger + if triggerWidget == widget: + currentPos = widget.index('@%d,%d' % (x, y)) + currentTags = widget.tag_names(currentPos) + if tagOrItem in currentTags: + if self._timer is not None: + self.after_cancel(self._timer) + self._timer = None + self.withdraw() + self.clearstatus() + self._currentTrigger = None + + def showstatus(self, statusHelp): + if self['state'] in ('status', 'both'): + cmd = self['statuscommand'] + if callable(cmd): + cmd(statusHelp) + + def clearstatus(self): + self.showstatus(None) + + def _state(self): + if self['state'] not in ('both', 'balloon', 'status', 'none'): + raise ValueError, 'bad state option ' + repr(self['state']) + \ + ': should be one of \'both\', \'balloon\', ' + \ + '\'status\' or \'none\'' + + def _relmouse(self): + if self['relmouse'] not in ('both', 'x', 'y', 'none'): + raise ValueError, 'bad relmouse option ' + repr(self['relmouse'])+ \ + ': should be one of \'both\', \'x\', ' + '\'y\' or \'none\'' + + def _enter(self, event, widget, statusHelp, balloonHelp, isItem): + + # Do not display balloon if mouse button is pressed. This + # will only occur if the button was pressed inside a widget, + # then the mouse moved out of and then back into the widget, + # with the button still held down. The number 0x1f00 is the + # button mask for the 5 possible buttons in X. + buttonPressed = (event.state & 0x1f00) != 0 + + if not buttonPressed and balloonHelp is not None and \ + self['state'] in ('balloon', 'both'): + if self._timer is not None: + self.after_cancel(self._timer) + self._timer = None + + self._timer = self.after(self['initwait'], + lambda self = self, widget = widget, help = balloonHelp, + isItem = isItem: + self._showBalloon(widget, help, isItem)) + + if isItem: + if hasattr(widget, 'canvasx'): + # The widget is a canvas. + item = widget.find_withtag('current') + if len(item) > 0: + item = item[0] + else: + item = None + self._currentTrigger = (widget, item) + else: + # The widget is a text widget. + self._currentTrigger = (widget, event.x, event.y) + else: + self._currentTrigger = (widget,) + + self.showstatus(statusHelp) + + def _leave(self, event): + if self._timer is not None: + self.after_cancel(self._timer) + self._timer = None + self.withdraw() + self.clearstatus() + self._currentTrigger = None + + def _destroy(self, event): + + # Only withdraw the balloon and cancel the timer if the widget + # being destroyed is the widget that triggered the balloon. + # Note that in a Tkinter Destroy event, the widget field is a + # string and not a widget as usual. + + if self._currentTrigger is None: + # The balloon is not currently being displayed + return + + if len(self._currentTrigger) == 1: + # The current trigger is a widget (not an item) + triggerWidget = self._currentTrigger[0] + if str(triggerWidget) == event.widget: + if self._timer is not None: + self.after_cancel(self._timer) + self._timer = None + self.withdraw() + self.clearstatus() + self._currentTrigger = None + + def _buttonpress(self, event): + if self._timer is not None: + self.after_cancel(self._timer) + self._timer = None + self.withdraw() + self._currentTrigger = None + + def _showBalloon(self, widget, balloonHelp, isItem): + + self._label.configure(text = balloonHelp) + + # First, display the balloon offscreen to get dimensions. + screenWidth = self.winfo_screenwidth() + screenHeight = self.winfo_screenheight() + self.geometry('+%d+0' % (screenWidth + 1)) + self.update_idletasks() + + if isItem: + # Get the bounding box of the current item. + bbox = widget.bbox('current') + if bbox is None: + # The item that triggered the balloon has disappeared, + # perhaps by a user's timer event that occured between + # the event and the 'initwait' timer calling + # this method. + return + + # The widget is either a text or canvas. The meaning of + # the values returned by the bbox method is different for + # each, so use the existence of the 'canvasx' method to + # distinguish between them. + if hasattr(widget, 'canvasx'): + # The widget is a canvas. Place balloon under canvas + # item. The positions returned by bbox are relative + # to the entire canvas, not just the visible part, so + # need to convert to window coordinates. + leftrel = bbox[0] - widget.canvasx(0) + toprel = bbox[1] - widget.canvasy(0) + bottomrel = bbox[3] - widget.canvasy(0) + else: + # The widget is a text widget. Place balloon under + # the character closest to the mouse. The positions + # returned by bbox are relative to the text widget + # window (ie the visible part of the text only). + leftrel = bbox[0] + toprel = bbox[1] + bottomrel = bbox[1] + bbox[3] + else: + leftrel = 0 + toprel = 0 + bottomrel = widget.winfo_height() + + xpointer, ypointer = widget.winfo_pointerxy() # -1 if off screen + + if xpointer >= 0 and self['relmouse'] in ('both', 'x'): + x = xpointer + else: + x = leftrel + widget.winfo_rootx() + x = x + self['xoffset'] + + if ypointer >= 0 and self['relmouse'] in ('both', 'y'): + y = ypointer + else: + y = bottomrel + widget.winfo_rooty() + y = y + self['yoffset'] + + edges = (string.atoi(str(self.cget('hull_highlightthickness'))) + + string.atoi(str(self.cget('hull_borderwidth')))) * 2 + if x + self._label.winfo_reqwidth() + edges > screenWidth: + x = screenWidth - self._label.winfo_reqwidth() - edges + + if y + self._label.winfo_reqheight() + edges > screenHeight: + if ypointer >= 0 and self['relmouse'] in ('both', 'y'): + y = ypointer + else: + y = toprel + widget.winfo_rooty() + y = y - self._label.winfo_reqheight() - self['yoffset'] - edges + + Pmw.setgeometryanddeiconify(self, '+%d+%d' % (x, y)) diff --git a/Pmw/Pmw_1_2/lib/PmwBase.py b/Pmw/Pmw_1_2/lib/PmwBase.py new file mode 100644 index 00000000..da38e9a4 --- /dev/null +++ b/Pmw/Pmw_1_2/lib/PmwBase.py @@ -0,0 +1,1933 @@ +# Pmw megawidget base classes. + +# This module provides a foundation for building megawidgets. It +# contains the MegaArchetype class which manages component widgets and +# configuration options. Also provided are the MegaToplevel and +# MegaWidget classes, derived from the MegaArchetype class. The +# MegaToplevel class contains a Tkinter Toplevel widget to act as the +# container of the megawidget. This is used as the base class of all +# megawidgets that are contained in their own top level window, such +# as a Dialog window. The MegaWidget class contains a Tkinter Frame +# to act as the container of the megawidget. This is used as the base +# class of all other megawidgets, such as a ComboBox or ButtonBox. +# +# Megawidgets are built by creating a class that inherits from either +# the MegaToplevel or MegaWidget class. + +import os +import string +import sys +import traceback +import types +import Tkinter + +# Special values used in index() methods of several megawidgets. +END = ['end'] +SELECT = ['select'] +DEFAULT = ['default'] + +# Constant used to indicate that an option can only be set by a call +# to the constructor. +INITOPT = ['initopt'] +_DEFAULT_OPTION_VALUE = ['default_option_value'] +_useTkOptionDb = 0 + +# Symbolic constants for the indexes into an optionInfo list. +_OPT_DEFAULT = 0 +_OPT_VALUE = 1 +_OPT_FUNCTION = 2 + +# Stacks + +_busyStack = [] + # Stack which tracks nested calls to show/hidebusycursor (called + # either directly or from activate()/deactivate()). Each element + # is a dictionary containing: + # 'newBusyWindows' : List of windows which had busy_hold called + # on them during a call to showbusycursor(). + # The corresponding call to hidebusycursor() + # will call busy_release on these windows. + # 'busyFocus' : The blt _Busy window which showbusycursor() + # set the focus to. + # 'previousFocus' : The focus as it was when showbusycursor() + # was called. The corresponding call to + # hidebusycursor() will restore this focus if + # the focus has not been changed from busyFocus. + +_grabStack = [] + # Stack of grabbed windows. It tracks calls to push/popgrab() + # (called either directly or from activate()/deactivate()). The + # window on the top of the stack is the window currently with the + # grab. Each element is a dictionary containing: + # 'grabWindow' : The window grabbed by pushgrab(). The + # corresponding call to popgrab() will release + # the grab on this window and restore the grab + # on the next window in the stack (if there is one). + # 'globalMode' : True if the grabWindow was grabbed with a + # global grab, false if the grab was local + # and 'nograb' if no grab was performed. + # 'previousFocus' : The focus as it was when pushgrab() + # was called. The corresponding call to + # popgrab() will restore this focus. + # 'deactivateFunction' : + # The function to call (usually grabWindow.deactivate) if + # popgrab() is called (usually from a deactivate() method) + # on a window which is not at the top of the stack (that is, + # does not have the grab or focus). For example, if a modal + # dialog is deleted by the window manager or deactivated by + # a timer. In this case, all dialogs above and including + # this one are deactivated, starting at the top of the + # stack. + + # Note that when dealing with focus windows, the name of the Tk + # widget is used, since it may be the '_Busy' window, which has no + # python instance associated with it. + +#============================================================================= + +# Functions used to forward methods from a class to a component. + +# Fill in a flattened method resolution dictionary for a class (attributes are +# filtered out). Flattening honours the MI method resolution rules +# (depth-first search of bases in order). The dictionary has method names +# for keys and functions for values. +def __methodDict(cls, dict): + + # the strategy is to traverse the class in the _reverse_ of the normal + # order, and overwrite any duplicates. + baseList = list(cls.__bases__) + baseList.reverse() + + # do bases in reverse order, so first base overrides last base + for super in baseList: + __methodDict(super, dict) + + # do my methods last to override base classes + for key, value in cls.__dict__.items(): + # ignore class attributes + if type(value) == types.FunctionType: + dict[key] = value + +def __methods(cls): + # Return all method names for a class. + + # Return all method names for a class (attributes are filtered + # out). Base classes are searched recursively. + + dict = {} + __methodDict(cls, dict) + return dict.keys() + +# Function body to resolve a forwarding given the target method name and the +# attribute name. The resulting lambda requires only self, but will forward +# any other parameters. +__stringBody = ( + 'def %(method)s(this, *args, **kw): return ' + + 'apply(this.%(attribute)s.%(method)s, args, kw)') + +# Get a unique id +__counter = 0 +def __unique(): + global __counter + __counter = __counter + 1 + return str(__counter) + +# Function body to resolve a forwarding given the target method name and the +# index of the resolution function. The resulting lambda requires only self, +# but will forward any other parameters. The target instance is identified +# by invoking the resolution function. +__funcBody = ( + 'def %(method)s(this, *args, **kw): return ' + + 'apply(this.%(forwardFunc)s().%(method)s, args, kw)') + +def forwardmethods(fromClass, toClass, toPart, exclude = ()): + # Forward all methods from one class to another. + + # Forwarders will be created in fromClass to forward method + # invocations to toClass. The methods to be forwarded are + # identified by flattening the interface of toClass, and excluding + # methods identified in the exclude list. Methods already defined + # in fromClass, or special methods with one or more leading or + # trailing underscores will not be forwarded. + + # For a given object of class fromClass, the corresponding toClass + # object is identified using toPart. This can either be a String + # denoting an attribute of fromClass objects, or a function taking + # a fromClass object and returning a toClass object. + + # Example: + # class MyClass: + # ... + # def __init__(self): + # ... + # self.__target = TargetClass() + # ... + # def findtarget(self): + # return self.__target + # forwardmethods(MyClass, TargetClass, '__target', ['dangerous1', 'dangerous2']) + # # ...or... + # forwardmethods(MyClass, TargetClass, MyClass.findtarget, + # ['dangerous1', 'dangerous2']) + + # In both cases, all TargetClass methods will be forwarded from + # MyClass except for dangerous1, dangerous2, special methods like + # __str__, and pre-existing methods like findtarget. + + + # Allow an attribute name (String) or a function to determine the instance + if type(toPart) != types.StringType: + + # check that it is something like a function + if callable(toPart): + + # If a method is passed, use the function within it + if hasattr(toPart, 'im_func'): + toPart = toPart.im_func + + # After this is set up, forwarders in this class will use + # the forwarding function. The forwarding function name is + # guaranteed to be unique, so that it can't be hidden by subclasses + forwardName = '__fwdfunc__' + __unique() + fromClass.__dict__[forwardName] = toPart + + # It's not a valid type + else: + raise TypeError, 'toPart must be attribute name, function or method' + + # get the full set of candidate methods + dict = {} + __methodDict(toClass, dict) + + # discard special methods + for ex in dict.keys(): + if ex[:1] == '_' or ex[-1:] == '_': + del dict[ex] + # discard dangerous methods supplied by the caller + for ex in exclude: + if dict.has_key(ex): + del dict[ex] + # discard methods already defined in fromClass + for ex in __methods(fromClass): + if dict.has_key(ex): + del dict[ex] + + for method, func in dict.items(): + d = {'method': method, 'func': func} + if type(toPart) == types.StringType: + execString = \ + __stringBody % {'method' : method, 'attribute' : toPart} + else: + execString = \ + __funcBody % {'forwardFunc' : forwardName, 'method' : method} + + exec execString in d + + # this creates a method + fromClass.__dict__[method] = d[method] + +#============================================================================= + +def setgeometryanddeiconify(window, geom): + # To avoid flashes on X and to position the window correctly on NT + # (caused by Tk bugs). + + if os.name == 'nt' or \ + (os.name == 'posix' and sys.platform[:6] == 'cygwin'): + # Require overrideredirect trick to stop window frame + # appearing momentarily. + redirect = window.overrideredirect() + if not redirect: + window.overrideredirect(1) + window.deiconify() + if geom is not None: + window.geometry(geom) + # Call update_idletasks to ensure NT moves the window to the + # correct position it is raised. + window.update_idletasks() + window.tkraise() + if not redirect: + window.overrideredirect(0) + else: + if geom is not None: + window.geometry(geom) + + # Problem!? Which way around should the following two calls + # go? If deiconify() is called first then I get complaints + # from people using the enlightenment or sawfish window + # managers that when a dialog is activated it takes about 2 + # seconds for the contents of the window to appear. But if + # tkraise() is called first then I get complaints from people + # using the twm window manager that when a dialog is activated + # it appears in the top right corner of the screen and also + # takes about 2 seconds to appear. + + #window.tkraise() + # Call update_idletasks to ensure certain window managers (eg: + # enlightenment and sawfish) do not cause Tk to delay for + # about two seconds before displaying window. + #window.update_idletasks() + #window.deiconify() + + window.deiconify() + if window.overrideredirect(): + # The window is not under the control of the window manager + # and so we need to raise it ourselves. + window.tkraise() + +#============================================================================= + +class MegaArchetype: + # Megawidget abstract root class. + + # This class provides methods which are inherited by classes + # implementing useful bases (this class doesn't provide a + # container widget inside which the megawidget can be built). + + def __init__(self, parent = None, hullClass = None): + + # Mapping from each megawidget option to a list of information + # about the option + # - default value + # - current value + # - function to call when the option is initialised in the + # call to initialiseoptions() in the constructor or + # modified via configure(). If this is INITOPT, the + # option is an initialisation option (an option that can + # be set by the call to the constructor but can not be + # used with configure). + # This mapping is not initialised here, but in the call to + # defineoptions() which precedes construction of this base class. + # + # self._optionInfo = {} + + # Mapping from each component name to a tuple of information + # about the component. + # - component widget instance + # - configure function of widget instance + # - the class of the widget (Frame, EntryField, etc) + # - cget function of widget instance + # - the name of the component group of this component, if any + self.__componentInfo = {} + + # Mapping from alias names to the names of components or + # sub-components. + self.__componentAliases = {} + + # Contains information about the keywords provided to the + # constructor. It is a mapping from the keyword to a tuple + # containing: + # - value of keyword + # - a boolean indicating if the keyword has been used. + # A keyword is used if, during the construction of a megawidget, + # - it is defined in a call to defineoptions() or addoptions(), or + # - it references, by name, a component of the megawidget, or + # - it references, by group, at least one component + # At the end of megawidget construction, a call is made to + # initialiseoptions() which reports an error if there are + # unused options given to the constructor. + # + # After megawidget construction, the dictionary contains + # keywords which refer to a dynamic component group, so that + # these components can be created after megawidget + # construction and still use the group options given to the + # constructor. + # + # self._constructorKeywords = {} + + # List of dynamic component groups. If a group is included in + # this list, then it not an error if a keyword argument for + # the group is given to the constructor or to configure(), but + # no components with this group have been created. + # self._dynamicGroups = () + + if hullClass is None: + self._hull = None + else: + if parent is None: + parent = Tkinter._default_root + + # Create the hull. + self._hull = self.createcomponent('hull', + (), None, + hullClass, (parent,)) + _hullToMegaWidget[self._hull] = self + + if _useTkOptionDb: + # Now that a widget has been created, query the Tk + # option database to get the default values for the + # options which have not been set in the call to the + # constructor. This assumes that defineoptions() is + # called before the __init__(). + option_get = self.option_get + _VALUE = _OPT_VALUE + _DEFAULT = _OPT_DEFAULT + for name, info in self._optionInfo.items(): + value = info[_VALUE] + if value is _DEFAULT_OPTION_VALUE: + resourceClass = string.upper(name[0]) + name[1:] + value = option_get(name, resourceClass) + if value != '': + try: + # Convert the string to int/float/tuple, etc + value = eval(value, {'__builtins__': {}}) + except: + pass + info[_VALUE] = value + else: + info[_VALUE] = info[_DEFAULT] + + def destroy(self): + # Clean up optionInfo in case it contains circular references + # in the function field, such as self._settitle in class + # MegaToplevel. + + self._optionInfo = {} + if self._hull is not None: + del _hullToMegaWidget[self._hull] + self._hull.destroy() + + #====================================================================== + # Methods used (mainly) during the construction of the megawidget. + + def defineoptions(self, keywords, optionDefs, dynamicGroups = ()): + # Create options, providing the default value and the method + # to call when the value is changed. If any option created by + # base classes has the same name as one in , the + # base class's value and function will be overriden. + + # This should be called before the constructor of the base + # class, so that default values defined in the derived class + # override those in the base class. + + if not hasattr(self, '_constructorKeywords'): + # First time defineoptions has been called. + tmp = {} + for option, value in keywords.items(): + tmp[option] = [value, 0] + self._constructorKeywords = tmp + self._optionInfo = {} + self._initialiseoptions_counter = 0 + self._initialiseoptions_counter = self._initialiseoptions_counter + 1 + + if not hasattr(self, '_dynamicGroups'): + self._dynamicGroups = () + self._dynamicGroups = self._dynamicGroups + tuple(dynamicGroups) + self.addoptions(optionDefs) + + def addoptions(self, optionDefs): + # Add additional options, providing the default value and the + # method to call when the value is changed. See + # "defineoptions" for more details + + # optimisations: + optionInfo = self._optionInfo + optionInfo_has_key = optionInfo.has_key + keywords = self._constructorKeywords + keywords_has_key = keywords.has_key + FUNCTION = _OPT_FUNCTION + + for name, default, function in optionDefs: + if '_' not in name: + # The option will already exist if it has been defined + # in a derived class. In this case, do not override the + # default value of the option or the callback function + # if it is not None. + if not optionInfo_has_key(name): + if keywords_has_key(name): + value = keywords[name][0] + optionInfo[name] = [default, value, function] + del keywords[name] + else: + if _useTkOptionDb: + optionInfo[name] = \ + [default, _DEFAULT_OPTION_VALUE, function] + else: + optionInfo[name] = [default, default, function] + elif optionInfo[name][FUNCTION] is None: + optionInfo[name][FUNCTION] = function + else: + # This option is of the form "component_option". If this is + # not already defined in self._constructorKeywords add it. + # This allows a derived class to override the default value + # of an option of a component of a base class. + if not keywords_has_key(name): + keywords[name] = [default, 0] + + def createcomponent(self, componentName, componentAliases, + componentGroup, widgetClass, *widgetArgs, **kw): + # Create a component (during construction or later). + + if self.__componentInfo.has_key(componentName): + raise ValueError, 'Component "%s" already exists' % componentName + + if '_' in componentName: + raise ValueError, \ + 'Component name "%s" must not contain "_"' % componentName + + if hasattr(self, '_constructorKeywords'): + keywords = self._constructorKeywords + else: + keywords = {} + for alias, component in componentAliases: + # Create aliases to the component and its sub-components. + index = string.find(component, '_') + if index < 0: + self.__componentAliases[alias] = (component, None) + else: + mainComponent = component[:index] + subComponent = component[(index + 1):] + self.__componentAliases[alias] = (mainComponent, subComponent) + + # Remove aliases from the constructor keyword arguments by + # replacing any keyword arguments that begin with *alias* + # with corresponding keys beginning with *component*. + + alias = alias + '_' + aliasLen = len(alias) + for option in keywords.keys(): + if len(option) > aliasLen and option[:aliasLen] == alias: + newkey = component + '_' + option[aliasLen:] + keywords[newkey] = keywords[option] + del keywords[option] + + componentPrefix = componentName + '_' + nameLen = len(componentPrefix) + for option in keywords.keys(): + if len(option) > nameLen and option[:nameLen] == componentPrefix: + # The keyword argument refers to this component, so add + # this to the options to use when constructing the widget. + kw[option[nameLen:]] = keywords[option][0] + del keywords[option] + else: + # Check if this keyword argument refers to the group + # of this component. If so, add this to the options + # to use when constructing the widget. Mark the + # keyword argument as being used, but do not remove it + # since it may be required when creating another + # component. + index = string.find(option, '_') + if index >= 0 and componentGroup == option[:index]: + rest = option[(index + 1):] + kw[rest] = keywords[option][0] + keywords[option][1] = 1 + + if kw.has_key('pyclass'): + widgetClass = kw['pyclass'] + del kw['pyclass'] + if widgetClass is None: + return None + if len(widgetArgs) == 1 and type(widgetArgs[0]) == types.TupleType: + # Arguments to the constructor can be specified as either + # multiple trailing arguments to createcomponent() or as a + # single tuple argument. + widgetArgs = widgetArgs[0] + widget = apply(widgetClass, widgetArgs, kw) + componentClass = widget.__class__.__name__ + self.__componentInfo[componentName] = (widget, widget.configure, + componentClass, widget.cget, componentGroup) + + return widget + + def destroycomponent(self, name): + # Remove a megawidget component. + + # This command is for use by megawidget designers to destroy a + # megawidget component. + + self.__componentInfo[name][0].destroy() + del self.__componentInfo[name] + + def createlabel(self, parent, childCols = 1, childRows = 1): + + labelpos = self['labelpos'] + labelmargin = self['labelmargin'] + if labelpos is None: + return + + label = self.createcomponent('label', + (), None, + Tkinter.Label, (parent,)) + + if labelpos[0] in 'ns': + # vertical layout + if labelpos[0] == 'n': + row = 0 + margin = 1 + else: + row = childRows + 3 + margin = row - 1 + label.grid(column=2, row=row, columnspan=childCols, sticky=labelpos) + parent.grid_rowconfigure(margin, minsize=labelmargin) + else: + # horizontal layout + if labelpos[0] == 'w': + col = 0 + margin = 1 + else: + col = childCols + 3 + margin = col - 1 + label.grid(column=col, row=2, rowspan=childRows, sticky=labelpos) + parent.grid_columnconfigure(margin, minsize=labelmargin) + + def initialiseoptions(self, dummy = None): + self._initialiseoptions_counter = self._initialiseoptions_counter - 1 + if self._initialiseoptions_counter == 0: + unusedOptions = [] + keywords = self._constructorKeywords + for name in keywords.keys(): + used = keywords[name][1] + if not used: + # This keyword argument has not been used. If it + # does not refer to a dynamic group, mark it as + # unused. + index = string.find(name, '_') + if index < 0 or name[:index] not in self._dynamicGroups: + unusedOptions.append(name) + if len(unusedOptions) > 0: + if len(unusedOptions) == 1: + text = 'Unknown option "' + else: + text = 'Unknown options "' + raise KeyError, text + string.join(unusedOptions, ', ') + \ + '" for ' + self.__class__.__name__ + + # Call the configuration callback function for every option. + FUNCTION = _OPT_FUNCTION + for info in self._optionInfo.values(): + func = info[FUNCTION] + if func is not None and func is not INITOPT: + func() + + #====================================================================== + # Method used to configure the megawidget. + + def configure(self, option=None, **kw): + # Query or configure the megawidget options. + # + # If not empty, *kw* is a dictionary giving new + # values for some of the options of this megawidget or its + # components. For options defined for this megawidget, set + # the value of the option to the new value and call the + # configuration callback function, if any. For options of the + # form _