El widget Entry
(Entrada de texto) permite que el texto sea tecleado y mostrado en una
simple caja de línea de texto. Hay una gran cantidad de teclas que funcionan por defecto.
Además, el usuario puede cambiar entre
el modo de inserción y el modo de sobreescritura pulsando la tecla Insert.
Para crear un nuevo widget Entry
, usa la siguiente función.
entryNew :: IO Entry
Para reemplazar o tomar el texto que está en el widget Entry
:
entrySetText :: EntryClass self => self -> String -> IO () entryGetText :: EntryClass self => self -> IO String
Si no queremos que se pueda modificar el contenido de un widget Entry
porque
alguien escriba en él, podemos cambiar su estado editable. También podemos modificar su
visibilidad (p. ej. para passwords), el número máximo de caracteres (0
si no hay máximo), si la entrada tiene un marco, o no, el número de caracteres para el
que se va a dejar espacio, y algunos otros atributos. También es posible usar completado de texto.
(mira EntryCompletion
en la documentación de la API). Los atributos de Entry
,
(accesibles por get
y set
) son:
entryEditable :: EntryClass self => Attr self Bool -- Por defecto True entryVisibility :: EntryClass self => Attr self Bool -- Por defecto True entryMaxLength :: EntryClass self => Attr self Int -- 0 sin máximo, límite 66535 entryHasFrame :: EntryClass self => Attr self Bool -- Por defecto False entryWidthChars :: EntryClass self => Attr self Int -- Por defecto -1, sin espacios
El tipo Entry
es una instancia de EditableClass
(Clase editable) y
muchos de sus métodos y atributos están definidos allí. Algunos especialmente útiles son:
editableInsertText :: EditableClass self => self -> String -> Int -> IO Int editableDeleteText :: EditableClass self -> Int -> Int -> IO () editableSelectRegion :: EditableClass self => self -> Int -> Int -> IO () editableDeleteSelection :: EditableClass self -> IO ()
donde los parámetros de tipo Int
denotan las posiciones apropiadas de inicio
y de finalización. El usuario también puede cortar, copiar y pegar a/desde el clipboard.
editableCutClipboard :: EditableClass self => self -> IO () editableCopyClipboard :: EditableClass self => self -> IO () editablePasteClipboard :: EditableClass self => self -> IO ()
Todas estas toman la posición actual del cursor. Puedes obtener y establecer dicha posición con:
editableGetPosition :: EditableClass self => self -> IO Int editableSetPosition :: EditableClass self => self -> Int
El cursor se muestra antes del caracter con el índice indicado en el widget. El valor debe ser menor o igual al número de caracteres en el widget. El valor -1 indica que el cursor debe posicionarse después del último caracter en la entrada.
La clase Editable
tiene unas señales que usan funciones de orden mayor
(no las estudiamos aquí). El widget Entry
tiene una señal que se envia después que
el usuario pulsa la tecla Enter:
onEntryActivate :: EntryClass ec => ec -> IO () -> IO (ConnectId ec)
También hay señales que se envían cuando el texto se corta, copia o pega, o cuando el usuario cambia del modo insertar a sobreescribir.
Las barras de estado (Status Bars) son widgets simples usados para mostrar un mensaje de texto. Mantienen una pila de los mensajes que se les han enviado, de modo que al mostrar el mensaje actual, vuelven a mostrar los mensajes de texto anteriores. Por defecto el usuario puede modificar su tamaño.
Para poder permitir que diferentes partes de una aplicación usen la misma barra de estado
para mostrar los mensajes, el widget de la barra de estado emplea ContextId
s que
sirven para identificar diferentes "usuarios". Se muestra el mensaje en la parte superior de la pila,
independientemente de su contexto. Los mensajes se almacenan con un criterio ultimo en llegar
primero en salir, y no ordenados por identificador de contexto.
La barra de estado se crea con:
statusbarNew :: IO Statusbar
Para generar un nuevo ContextId
utilizo la siguiente función, con un
String
usado como descripción textual del contexto:
statusbarGetContextId :: StatusbarClass self => self -> String -> IO ContextId
Aquí hay tres funciones que pueden operar en las barras de estado:
statusbarPush :: StatusbarClass self => self -> ContextId -> String -> IO MessageId statusbarPop :: StatusbarClass self => self -> ContextId -> IO () statusbarRemove :: StatusbarClass self => self -> ContextId -> MessageId -> IO ()
La primera, statusbarPush
, se emplea para añadir un mensaje nuevo
a la barra de estado. Devuelve un MessageId
, que puede ser pasado más tarde a
statusbarRemove
para eliminar el mensaje en el ContextId
y MessageId
de la pila de la barra de estado.
La función statusbarPop
elimina el mensaje más alto de la pila dentro del identificador de contexto
aportado.
Las barras de estado, como las barras de progreso, se usan para mostrar mensajes al usuario sobre alguna operación en ejecución. En el ejemplo inferior, simulamos esta operación comprobando si el texto que envía el usuario (pulsando Enter) es el mismo que su inverso, y enviando el resultado a la pila. El usuario puede ver los resultados pulsando el botón de información, que muestra la pila de mensajes. La primera vez, la pila está vacía, así que el botón está sombreado, usando:
widgetSetSensitivity :: WidgetClass self => self -> Bool -> IO ()
Fíjate que la barra de estado no sería la primera opción aquí, ya que no se comprueba si la pila está vacía, pero el ejemplo muestra como se aplica. El manejador del cambio de tamaño de la ventana de la barra de estado no está muy claro, pero está ahí, abajo a la derecha.
import Graphics.UI.Gtk main :: IO () main= do initGUI window <- windowNew set window [windowTitle := "Text Entry", containerBorderWidth := 10] vb <- vBoxNew False 0 containerAdd window vb hb <- hBoxNew False 0 boxPackStart vb hb PackNatural 0 txtfield <- entryNew boxPackStart hb txtfield PackNatural 5 button <- buttonNewFromStock stockInfo boxPackStart hb button PackNatural 0 txtstack <- statusbarNew boxPackStart vb txtstack PackNatural 0 id <- statusbarGetContextId txtstack "Line" widgetShowAll window widgetSetSensitivity button False onEntryActivate txtfield (saveText txtfield button txtstack id) onPressed button (statusbarPop txtstack id) onDestroy window mainQuit mainGUI saveText :: Entry -> Button -> Statusbar -> ContextId -> IO () saveText fld b stk id = do txt <- entryGetText fld let mesg | txt == reverse txt = "\"" ++ txt ++ "\"" ++ " is equal to its reverse" | otherwise = "\"" ++ txt ++ "\"" ++ " is not equal to its reverse" widgetSetSensitivity b True msgid <- statusbarPush stk id mesg return ()