/* * Copyright (c) 2005-2009 Hypertriton, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 OR CONTRIBUTORS 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. */ #include #ifdef ENABLE_GUI #include #include #include #include #include #include #include "m.h" #include "m_matview.h" #include "m_gui.h" M_Matview * M_MatviewNew(void *parent, M_Matrix *M, Uint flags) { M_Matview *mv; mv = Malloc(sizeof(M_Matview)); AG_ObjectInit(mv, &mMatviewClass); mv->flags |= flags; if (M != NULL) { M_MatviewSetMatrix(mv, M); } AG_ObjectAttach(parent, mv); return (mv); } void M_MatviewSetMatrix(M_Matview *mv, M_Matrix *M) { M_MatrixFPU *MFPU = (void *)M; if (strcmp(M->ops->name, "scalar") != 0) { AG_FatalError("Cannot display %s matrices", M->ops->name); } AG_ObjectLock(mv); mv->matrix = MMATRIX(MFPU); mv->mPre = MROWS(MFPU); mv->nPre = MCOLS(MFPU); AG_BindInt(mv->hBar, "max", (int *)&MMATRIX(mv->matrix)->m); AG_BindInt(mv->vBar, "max", (int *)&MMATRIX(mv->matrix)->n); AG_ObjectUnlock(mv); } static void KeyDown(AG_Event *event) { M_Matview *mv = AG_SELF(); int keysym = AG_INT(1); switch (keysym) { case SDLK_g: M_MatviewSetDisplayMode(mv, M_MATVIEW_GREYSCALE); break; case SDLK_n: M_MatviewSetDisplayMode(mv, M_MATVIEW_NUMERICAL); break; case SDLK_EQUALS: mv->scale++; break; case SDLK_MINUS: if (mv->scale-1 >= 0) { mv->scale--; } break; } } static void MouseButtonDown(AG_Event *event) { AG_Button *bu = AG_SELF(); AG_WidgetFocus(bu); } static void Init(void *obj) { M_Matview *mv = obj; WIDGET(mv)->flags |= AG_WIDGET_EXPAND|AG_WIDGET_FOCUSABLE; mv->mode = M_MATVIEW_NUMERICAL; mv->matrix = NULL; mv->flags = 0; mv->hSpacing = 2; mv->vSpacing = 2; mv->hBar = AG_ScrollbarNew(mv, AG_SCROLLBAR_HORIZ, 0); mv->vBar = AG_ScrollbarNew(mv, AG_SCROLLBAR_VERT, 0); mv->xOffs = 0; mv->yOffs = 0; mv->scale = 8; mv->mPre = 0; mv->nPre = 0; mv->numFmt = "%g"; mv->tCache = AG_TextCacheNew(mv, 64, 16); mv->r = AG_RECT(0,0,0,0); AG_BindInt(mv->hBar, "value", &mv->xOffs); AG_BindInt(mv->vBar, "value", &mv->yOffs); AG_SetInt(mv->hBar, "min", 0); AG_SetInt(mv->vBar, "min", 0); AG_TextSize("-00", &mv->wEnt, &mv->hEnt); AG_SetEvent(mv, "window-keydown", KeyDown, NULL); AG_SetEvent(mv, "window-mousebuttondown", MouseButtonDown, NULL); } static void Destroy(void *obj) { M_Matview *mv = obj; if (mv->tCache != NULL) AG_TextCacheDestroy(mv->tCache); } void M_MatviewSetDisplayMode(M_Matview *mv, enum m_matview_mode mode) { AG_ObjectLock(mv); mv->mode = mode; AG_ObjectUnlock(mv); } void M_MatviewSetNumericalFmt(M_Matview *mv, const char *fmt) { AG_ObjectLock(mv); mv->numFmt = fmt; AG_ObjectUnlock(mv); } void M_MatviewSizeHint(M_Matview *mv, const char *text, Uint m, Uint n) { AG_ObjectLock(mv); mv->mPre = m; mv->nPre = n; AG_TextSize(text, &mv->wEnt, &mv->hEnt); AG_ObjectUnlock(mv); } static void SizeRequest(void *obj, AG_SizeReq *r) { M_Matview *mv = obj; r->w = mv->nPre*(mv->wEnt + mv->hSpacing) + mv->hSpacing*2; r->h = mv->mPre*(mv->hEnt + mv->vSpacing) + mv->vSpacing*2; } static int SizeAllocate(void *obj, const AG_SizeAlloc *a) { M_Matview *mv = obj; AG_SizeAlloc aBar; mv->r.w = a->w; mv->r.h = a->h; aBar.x = 0; aBar.y = a->h - mv->hBar->wButton; aBar.w = a->w; aBar.h = mv->hBar->wButton+1; AG_WidgetSizeAlloc(mv->hBar, &aBar); mv->r.h -= HEIGHT(mv->hBar); aBar.x = a->w - mv->vBar->wButton; aBar.y = mv->vBar->wButton; aBar.w = mv->vBar->wButton; aBar.h = a->h - mv->hBar->wButton+1; AG_WidgetSizeAlloc(mv->vBar, &aBar); mv->r.w -= WIDTH(mv->vBar); return (0); } static void DrawNumerical(void *p) { char text[8]; M_Matview *mv = p; M_Matrix *M = mv->matrix; int m, n; int x, y; int xMin = 5, xMax = 0; int xOffs = -mv->xOffs*mv->wEnt + 8; int yOffs = -mv->yOffs*mv->hEnt + 8; int su; AG_DrawBox(mv, mv->r, -1, AG_COLOR(BG_COLOR)); AG_PushClipRect(mv, mv->r); AG_PushTextState(); AG_TextColor(TEXT_COLOR); for (m = 0, y = yOffs; m < MROWS(M) && y < mv->r.h; m++, y += (mv->hEnt + mv->vSpacing)) { for (n = 0, x = xOffs; n < MCOLS(M) && x < mv->r.w; n++, x += (mv->wEnt + mv->hSpacing)) { Snprintf(text, sizeof(text), mv->numFmt, M_Get(M,m,n)); su = AG_TextCacheGet(mv->tCache,text); AG_WidgetBlitSurface(mv, su, x, y); xMax = MAX(xMax, x+WSURFACE(mv,su)->w); xMin = MIN(xMin, x); } } AG_DrawLineV(mv, xMin-2, 2, y, AG_COLOR(TEXT_COLOR)); AG_DrawLineV(mv, xMax+4, 2, y, AG_COLOR(TEXT_COLOR)); AG_PopTextState(); AG_PopClipRect(); } static void DrawGreyscale(void *p) { M_Matview *mv = p; M_Matrix *A = mv->matrix; Uint m, n; int x, y; M_Real big = 0.0, small = 0.0; int xOffs = -mv->xOffs*mv->scale; int yOffs = -mv->yOffs*mv->scale; AG_DrawBox(mv, mv->r, -1, AG_COLOR(BG_COLOR)); AG_PushClipRect(mv, mv->r); for (m = 0; m < MROWS(A); m++) { for (n = 0; n < MCOLS(A); n++) { if (M_Get(A,m,n) == 0.0) { continue; } if (M_Get(A,m,n) > big) { big = M_Get(A,m,n); } if (M_Get(A,m,n) < small) { small = M_Get(A,m,n); } } } big -= small; for (m = 0, y = yOffs; m < MROWS(A) && y < mv->r.h; m++, y += mv->scale) { for (n = 0, x = xOffs; n < MCOLS(A) && x < mv->r.w; n++, x += mv->scale) { M_Real dv = M_Get(A,m,n); Uint32 c; Uint8 v; if (dv == 0.0) { continue; } if (dv == HUGE_VAL) { c = AG_MapRGB(agVideoFmt, 200,0,0); } else { if (dv >= 0.0) { v = 127 + (Uint8)(dv*127.0/big); c = AG_MapRGB(agVideoFmt, v,0,0); } else { v = 127 + (Uint8)(Fabs(dv)*127.0/big); c = AG_MapRGB(agVideoFmt, 0,0,v); } } AG_DrawRectFilled(mv, AG_RECT(x,y,mv->scale,mv->scale), c); } } AG_PopClipRect(); } static void Draw(void *obj) { M_Matview *mv = obj; if (mv->mode == M_MATVIEW_NUMERICAL) { DrawNumerical(mv); } else { DrawGreyscale(mv); } } AG_WidgetClass mMatviewClass = { { "AG_Widget:M_Matview", sizeof(M_Matview), { 0,0 }, Init, NULL, /* free */ Destroy, NULL, /* load */ NULL, /* save */ NULL /* edit */ }, Draw, SizeRequest, SizeAllocate }; #endif /* ENABLE_GUI */