Add textEntry class (warning: unfinished) to betawidget.
git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@5920 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
a31fbb4561
commit
7453cee5bb
|
@ -0,0 +1,154 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "textEntry.h"
|
||||
|
||||
static textEntryVtbl vtbl;
|
||||
|
||||
// Default size of the text buffer
|
||||
static const int defautSize = 128;
|
||||
|
||||
const classInfo textEntryClassInfo =
|
||||
{
|
||||
&widgetClassInfo,
|
||||
"textEntry"
|
||||
};
|
||||
|
||||
textEntry *textEntryCreate(const char *id)
|
||||
{
|
||||
textEntry *instance = malloc(sizeof(textEntry));
|
||||
|
||||
if (instance == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Call the constructor
|
||||
textEntryInit(instance, id);
|
||||
|
||||
// Return the new object
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void textEntryInitVtbl(textEntry *self)
|
||||
{
|
||||
static bool initialised = false;
|
||||
|
||||
if (!initialised)
|
||||
{
|
||||
// Copy our parents vtable into ours
|
||||
vtbl.widgetVtbl = *(WIDGET(self)->vtbl);
|
||||
|
||||
// Overload the destroy method
|
||||
vtbl.widgetVtbl.destroy = textEntryDestroyImpl;
|
||||
|
||||
// Draw method
|
||||
vtbl.widgetVtbl.doDraw = textEntryDoDrawImpl;
|
||||
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
// Replace our parents vtable with our own
|
||||
WIDGET(self)->vtbl = &vtbl.widgetVtbl;
|
||||
|
||||
// Set our vtable
|
||||
self->vtbl = &vtbl;
|
||||
}
|
||||
|
||||
void textEntryInit(textEntry *self, const char *id)
|
||||
{
|
||||
// Init our parent
|
||||
widgetInit(WIDGET(self), id);
|
||||
|
||||
// Prepare our vtable
|
||||
textEntryInitVtbl(self);
|
||||
|
||||
// Set our type
|
||||
WIDGET(self)->classInfo = &textEntryClassInfo;
|
||||
|
||||
// Allocate a modestly sized text buffer
|
||||
self->text = calloc(defautSize, 1);
|
||||
self->textSize = defautSize;
|
||||
|
||||
// On account of there being no text, all of these are 0
|
||||
self->textHead = 0;
|
||||
self->insertPosition = 0;
|
||||
self->renderLeftOffset = 0;
|
||||
}
|
||||
|
||||
void textEntryDestroyImpl(widget *self)
|
||||
{
|
||||
// Free the text buffer
|
||||
free(TEXT_ENTRY(self)->text);
|
||||
|
||||
// Call our parents destructor
|
||||
widgetDestroyImpl(self);
|
||||
}
|
||||
|
||||
void textEntryDoDrawImpl(widget *self)
|
||||
{
|
||||
// Draw our frame
|
||||
textEntryDoDrawFrame(TEXT_ENTRY(self));
|
||||
textEntryDoDrawText(TEXT_ENTRY(self));
|
||||
}
|
||||
|
||||
void textEntryDoDrawFrame(textEntry *self)
|
||||
{
|
||||
cairo_t *cr = WIDGET(self)->cr;
|
||||
|
||||
// Lets keep it simple
|
||||
cairo_rectangle(cr, 0, 0, WIDGET(self)->size.x, WIDGET(self)->size.y);
|
||||
cairo_set_source_rgba(cr, 0.0, 1.0, 1.0, 0.4);
|
||||
cairo_fill_preserve(cr);
|
||||
|
||||
// Black stroke
|
||||
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
|
||||
cairo_set_line_width(cr, 2);
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
|
||||
void textEntryDoDrawText(textEntry *self)
|
||||
{
|
||||
cairo_t *cr = WIDGET(self)->cr;
|
||||
|
||||
// Set the render left offset
|
||||
cairo_translate(cr, -self->renderLeftOffset, 0);
|
||||
|
||||
// Draw the text
|
||||
cairo_move_to(cr, 0, WIDGET(self)->size.y);
|
||||
|
||||
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
|
||||
CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size(cr, 25);
|
||||
|
||||
cairo_show_text(cr, self->text);
|
||||
|
||||
// Restore the offset
|
||||
cairo_translate(cr, self->renderLeftOffset, 0);
|
||||
}
|
||||
|
||||
const char *textEntryGetContents(textEntry *self)
|
||||
{
|
||||
return self->text;
|
||||
}
|
||||
|
||||
bool textEntrySetContents(textEntry *self, const char *contents)
|
||||
{
|
||||
// Free the current contents
|
||||
free(self->text);
|
||||
|
||||
// Copy the new contents
|
||||
self->text = strdup(contents);
|
||||
|
||||
// TODO: Check for NULL and return false
|
||||
|
||||
// Update the size information
|
||||
self->textHead = self->textSize = strlen(contents);
|
||||
|
||||
// Place the caret at the start of the string
|
||||
self->insertPosition = 0;
|
||||
|
||||
// Since the insert position is the far left, the render offset is 0
|
||||
self->renderLeftOffset = 0;
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
#ifndef TEXTENTRY_H_
|
||||
#define TEXTENTRY_H_
|
||||
|
||||
#include "widget.h"
|
||||
|
||||
/*
|
||||
* Forward declarations
|
||||
*/
|
||||
typedef struct _textEntry textEntry;
|
||||
typedef struct _textEntryVtbl textEntryVtbl;
|
||||
|
||||
struct _textEntryVtbl
|
||||
{
|
||||
widgetVtbl widgetVtbl;
|
||||
};
|
||||
|
||||
struct _textEntry
|
||||
{
|
||||
/*
|
||||
* Parent
|
||||
*/
|
||||
widget widget;
|
||||
|
||||
/*
|
||||
* Our vtable
|
||||
*/
|
||||
textEntryVtbl *vtbl;
|
||||
|
||||
/*
|
||||
* The character buffer (contents), UTF-8 encoded
|
||||
*/
|
||||
char *text;
|
||||
|
||||
/*
|
||||
* The size of text (how much space was allocated), not including the '\0'
|
||||
* byte
|
||||
*/
|
||||
size_t textSize;
|
||||
|
||||
/*
|
||||
* The actual length of the string (how much space is used); since text is
|
||||
* encoded in UTF-8 this is *not* the character count
|
||||
*/
|
||||
size_t textHead;
|
||||
|
||||
/*
|
||||
* The current insert position (where in the byte-stream characters should
|
||||
* be inserted to); again this has no relation to the character count
|
||||
*/
|
||||
int insertPosition;
|
||||
|
||||
/*
|
||||
* The offet of the leftmost pixel that is to be rendered:
|
||||
* |*-------------------|
|
||||
* "The rain in S|pain falls mainly on|the..."
|
||||
* |--------------------|
|
||||
*
|
||||
* The * shows the location represented by this value
|
||||
*/
|
||||
int renderLeftOffset;
|
||||
};
|
||||
|
||||
/*
|
||||
* Type information
|
||||
*/
|
||||
extern const classInfo textEntryClassInfo;
|
||||
|
||||
/*
|
||||
* Helper macros
|
||||
*/
|
||||
#define TEXT_ENTRY(self) (assert(widgetIsA(WIDGET(self), &textEntryClassInfo)), \
|
||||
(textEntry *) (self))
|
||||
|
||||
/*
|
||||
* Protected methods
|
||||
*/
|
||||
void textEntryInit(textEntry *self, const char *id);
|
||||
void textEntryDestroyImpl(widget *self);
|
||||
void textEntryDoDrawImpl(widget *self);
|
||||
size textEntryGetMinSizeImpl(widget *self);
|
||||
size textEntryGetMaxSizeImpl(widget *self);
|
||||
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructs a new textEntry object and returns it.
|
||||
*
|
||||
* @param id The id of the widget.
|
||||
* @return A pointer to an textEntry on success; otherwise NULL.
|
||||
*/
|
||||
textEntry *textEntryCreate(const char *id);
|
||||
|
||||
/**
|
||||
* Fetches the contents of the text entry field, returning a copy of them. It is
|
||||
* important to note that the returned string remains the responsibility of the
|
||||
* user and must be free'ed when no longer required.
|
||||
*
|
||||
* @param self The text entry field to get the contents of.
|
||||
* @return A pointer to a freshly allocated copy of the contents on success;
|
||||
* otherwise NULL.
|
||||
*/
|
||||
const char *textEntryGetContents(textEntry *self);
|
||||
|
||||
/**
|
||||
* Sets the contents of the entry field to a copy of the contents of contents.
|
||||
*
|
||||
* @param self The text entry to set the contents of.
|
||||
* @param contents The string to set the contents to. This should be UTF-8
|
||||
* encoded and NULL terminated.
|
||||
* @return true if the contents were successfully set; otherwise false.
|
||||
*/
|
||||
bool textEntrySetContents(textEntry *self, const char *contents);
|
||||
|
||||
/*
|
||||
* Protected methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called by widgetDoDraw to draw the frame of the text entry field. The frame
|
||||
* consists of the background and border of the entry field. This method will be
|
||||
* called before the text and caret are rendered.
|
||||
*
|
||||
* @param self The text entry to draw the frame of.
|
||||
*/
|
||||
void textEntryDoDrawFrame(textEntry *self);
|
||||
|
||||
void textEntryDoDrawText(textEntry *self);
|
||||
|
||||
#endif /*TEXTENTRY_H_*/
|
Loading…
Reference in New Issue