drawer.cpp

Go to the documentation of this file.
00001 /*
00002  * drawer.cpp
00003  *
00004  * Copyright (C) 2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Dumb drawer that just writes to ASCII strings.  Helpful for testing.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "drawer.h"             // always include our own header first!
00036 
00037 #include "common/wave_ex.h"
00038 
00039 
00040 namespace dialog {
00041 
00042 /// \ingroup dialog
00043 /*@{*/
00044 
00045 
00046 // Drawer interface destructor
00047 Drawer::~Drawer(void) throw() { }
00048 TextDrawer::~TextDrawer(void) throw() { }
00049 
00050 
00051 static const int s_maxText              = 147;
00052 static const int s_maxDim               = s_maxText + 1;
00053 
00054 
00055 ////////////////////////////////////////////////////////////////////////////////
00056 //
00057 //      static helper methods
00058 //
00059 ////////////////////////////////////////////////////////////////////////////////
00060 
00061 
00062 ////////////////////////////////////////////////////////////////////////////////
00063 //
00064 //      TDI -- class that implements the TextDrawer interface
00065 //
00066 ////////////////////////////////////////////////////////////////////////////////
00067 
00068 class TDI : public TextDrawer {
00069 public:
00070         ~TDI(void) throw() { }
00071 
00072         // public class methods ------------------------------------------------
00073         void initialize(IN int borderSize) throw();
00074 
00075         // dialog::Drawer class interface methods ------------------------------
00076         font_size_t getFontSizing(IN eElementType type,
00077                                 IN const char * text) {
00078                         font_size_t fs;
00079                         fs.lead = 0;
00080                         fs.trail = strlen(text);
00081                         fs.rise = 1;
00082                         fs.drop = 0;
00083                         return fs;
00084                 }
00085 
00086         border_size_t getBorderSizing(IN eElementType type) {
00087                         border_size_t bs;
00088                         bs.size = m_borderSize;
00089                         return bs;
00090                 }
00091 
00092         void drawString(IN eElementType type,
00093                                 IN const point_t& pos,
00094                                 IN const char * text);
00095 
00096         void drawRectWithBorder(IN eElementType type,
00097                                 IN const rect_t& r);
00098 
00099         void drawCircle(IN const point_t& pos,
00100                                 IN float radius) { /* not implemented! */ };
00101 
00102         // dialog::TextDrawer class interface methods --------------------------
00103         void writeToStream(IO std::ostream& stream);
00104 
00105 private:
00106         // private helper methods ----------------------------------------------
00107         struct row_t {
00108                 char            text[s_maxDim];
00109         };
00110 
00111         void markUsed(IN int iRow) throw() {
00112                         ASSERT(iRow >= 0 && iRow < s_maxDim,
00113                             "Bad row index: %d", iRow);
00114                         row_t& r = m_rows[iRow];
00115                         if (!r.text[0]) {
00116                                 r.text[0] = ' ';
00117                         }
00118                 }
00119 
00120         // private member data -------------------------------------------------
00121         row_t           m_rows[s_maxDim];
00122         int             m_borderSize;
00123 };
00124 
00125 
00126 
00127 void
00128 TDI::initialize
00129 (
00130 IN int borderSize
00131 )
00132 throw()
00133 {
00134         ASSERT2(borderSize > 0, "Bad border size: " << borderSize);
00135 
00136         m_borderSize = borderSize;
00137         for (int y = 0; y < s_maxDim; ++y) {
00138                 row_t& r = m_rows[y];
00139 
00140                 r.text[0] = 0;          // flag as unused
00141                 for (int x = 1; x < s_maxText; ++x) {
00142                         r.text[x] = ' ';
00143                 }
00144                 r.text[s_maxText] = 0;  // null-terminate
00145         }
00146 }
00147 
00148 
00149 
00150 ////////////////////////////////////////////////////////////////////////////////
00151 //
00152 //      TDI -- dialog::Drawer and dialog::TextDrawer class interface methods
00153 //
00154 ////////////////////////////////////////////////////////////////////////////////
00155 
00156 
00157 void
00158 TDI::drawString
00159 (
00160 IN eElementType type,
00161 IN const point_t& pos,
00162 IN const char * text
00163 )
00164 {
00165         ASSERT(text, "null");
00166         ASSERT2(pos.y >= 0 && pos.y < s_maxDim, "bad pos.y: " << pos.y);
00167 
00168         int L = strlen(text);
00169         ASSERT2(pos.x >= 0 && pos.x + L < s_maxDim, "bad pos.x: " << pos.x
00170             << "   or bad L: " << L);
00171 
00172         row_t& r = m_rows[pos.y];
00173         this->markUsed(pos.y);
00174         for (int i = 0; i < L; ++i) {
00175                 r.text[pos.x + i] = text[i];
00176         }
00177 }
00178 
00179 
00180 
00181 void
00182 TDI::drawRectWithBorder
00183 (
00184 IN eElementType type,
00185 IN const rect_t& r
00186 )
00187 {
00188         ASSERT2(r.isValid(), "bad r");
00189         ASSERT2(r.top >= 0, "bad top: " << r.top);
00190         ASSERT2(r.left >= 0, "bad left: " << r.left);
00191         ASSERT2(r.right < s_maxDim, "bad right: " << r.right);
00192         ASSERT2(r.bottom < s_maxDim, "bad bottom: " << r.bottom);
00193 
00194         // top and bottom rows
00195         row_t& tRow = m_rows[r.top];
00196         row_t& bRow = m_rows[r.bottom - 1];
00197         this->markUsed(r.top);
00198         this->markUsed(r.bottom - 1);
00199         tRow.text[r.left] = '/';
00200         tRow.text[r.right - 1] = '\\';
00201         bRow.text[r.left] = '\\';
00202         bRow.text[r.right - 1] = '/';
00203         for (int i = r.left + 1; i < r.right - 1; ++i) {
00204                 tRow.text[i] = '-';
00205                 bRow.text[i] = '-';
00206         }
00207 
00208         // intermediate rows: just endpoints
00209         for (int i = r.top + 1; i < r.bottom - 1; ++i) {
00210                 row_t& row = m_rows[i];
00211                 this->markUsed(i);
00212                 row.text[r.left] = '|';
00213                 row.text[r.right - 1] = '|';
00214         }
00215 }
00216 
00217 
00218 
00219 void
00220 TDI::writeToStream
00221 (
00222 IO std::ostream& stream
00223 )
00224 {
00225         for (int i = 0; i < s_maxDim; ++i) {
00226                 const row_t& r = m_rows[i];
00227                 if (!r.text[0])
00228                         continue;               // skip this row--unused
00229                 stream << r.text << "\n";
00230         }
00231 }
00232 
00233 
00234 
00235 ////////////////////////////////////////////////////////////////////////////////
00236 //
00237 //      public API
00238 //
00239 ////////////////////////////////////////////////////////////////////////////////
00240 
00241 smart_ptr<TextDrawer>
00242 TextDrawer::create
00243 (
00244 IN int borderSize
00245 )
00246 {
00247         ASSERT2(borderSize > 0, "Bad border size: " << borderSize);
00248 
00249         smart_ptr<TDI> local = new TDI;
00250         ASSERT(local, "out of memory");
00251 
00252         local->initialize(borderSize);
00253 
00254         return local;
00255 }
00256 
00257 
00258 
00259 };      // dialog namespace
00260