FreeCAD

Форк
0
/
FeatureViewSpreadsheet.cpp 
297 строк · 13.7 Кб
1
/***************************************************************************
2
 *   Copyright (c) Yorik van Havre          (yorik@uncreated.net) 2015     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
#include <iomanip>
26
#include <sstream>
27
#endif
28

29
#include <App/PropertyUnits.h>
30
#include <Base/Exception.h>
31
#include <Mod/Spreadsheet/App/Cell.h>
32
#include <Mod/Spreadsheet/App/Sheet.h>
33

34
#include "FeatureViewSpreadsheet.h"
35

36

37
using namespace Drawing;
38

39
//===========================================================================
40
// FeatureViewSpreadsheet
41
//===========================================================================
42

43
PROPERTY_SOURCE(Drawing::FeatureViewSpreadsheet, Drawing::FeatureView)
44

45

46
FeatureViewSpreadsheet::FeatureViewSpreadsheet(void)
47
{
48
    static const char* vgroup = "Drawing view";
49

50
    ADD_PROPERTY_TYPE(CellStart,
51
                      ("A1"),
52
                      vgroup,
53
                      App::Prop_None,
54
                      "The top left cell of the range to display");
55
    ADD_PROPERTY_TYPE(CellEnd,
56
                      ("B2"),
57
                      vgroup,
58
                      App::Prop_None,
59
                      "The bottom right cell of the range to display");
60
    ADD_PROPERTY_TYPE(Font, ("Sans"), vgroup, App::Prop_None, "The name of the font to use");
61
    ADD_PROPERTY_TYPE(Color,
62
                      (0.0f, 0.0f, 0.0f),
63
                      vgroup,
64
                      App::Prop_None,
65
                      "The default color of the text and lines");
66
    ADD_PROPERTY_TYPE(Source, (nullptr), vgroup, App::Prop_None, "Spreadsheet to view");
67
    ADD_PROPERTY_TYPE(LineWidth, (0.35), vgroup, App::Prop_None, "The thickness of the cell lines");
68
    ADD_PROPERTY_TYPE(FontSize, (12.0), vgroup, App::Prop_None, "The size of the text");
69
}
70

71

72
FeatureViewSpreadsheet::~FeatureViewSpreadsheet()
73
{}
74

75
App::DocumentObjectExecReturn* FeatureViewSpreadsheet::execute(void)
76
{
77
    // quick tests
78
    App::DocumentObject* link = Source.getValue();
79
    std::string scellstart = CellStart.getValue();
80
    std::string scellend = CellEnd.getValue();
81
    if (!link) {
82
        return new App::DocumentObjectExecReturn("No spreadsheet linked");
83
    }
84
    if (!link->isDerivedFrom<Spreadsheet::Sheet>()) {
85
        return new App::DocumentObjectExecReturn("The linked object is not a spreadsheet");
86
    }
87
    if ((scellstart.empty()) || (scellend.empty())) {
88
        return new App::DocumentObjectExecReturn("Empty cell value");
89
    }
90

91
    // build a list of available columns: A, B, C, ... AA, AB, ... ZY, ZZ.
92
    std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
93
    std::vector<std::string> availcolumns;
94
    for (int i = 0; i < 26; ++i) {
95
        std::stringstream s;
96
        s << alphabet[i];
97
        availcolumns.push_back(s.str());
98
    }
99
    for (int i = 0; i < 26; ++i) {
100
        for (int j = 0; i < 26; ++i) {
101
            std::stringstream s;
102
            s << alphabet[i] << alphabet[j];
103
            availcolumns.push_back(s.str());
104
        }
105
    }
106

107
    // build rows range and columns range
108
    std::vector<std::string> columns;
109
    std::vector<int> rows;
110
    try {
111
        for (unsigned int i = 0; i < scellstart.length(); ++i) {
112
            if (isdigit(scellstart[i])) {
113
                columns.push_back(scellstart.substr(0, i));
114
                rows.push_back(std::atoi(scellstart.substr(i, scellstart.length() - 1).c_str()));
115
            }
116
        }
117
        for (unsigned int i = 0; i < scellend.length(); ++i) {
118
            if (isdigit(scellend[i])) {
119
                std::string startcol = columns.back();
120
                std::string endcol = scellend.substr(0, i);
121
                bool valid = false;
122
                for (std::vector<std::string>::const_iterator j = availcolumns.begin();
123
                     j != availcolumns.end();
124
                     ++j) {
125
                    if ((*j) == startcol) {
126
                        if ((*j) != endcol) {
127
                            valid = true;
128
                        }
129
                    }
130
                    else {
131
                        if (valid) {
132
                            if ((*j) == endcol) {
133
                                columns.push_back((*j));
134
                                valid = false;
135
                            }
136
                            else {
137
                                columns.push_back((*j));
138
                            }
139
                        }
140
                    }
141
                }
142
                int endrow = std::atoi(scellend.substr(i, scellend.length() - 1).c_str());
143
                for (int j = rows.back() + 1; j <= endrow; ++j) {
144
                    rows.push_back(j);
145
                }
146
            }
147
        }
148
    }
149
    catch (std::exception&) {
150
        return new App::DocumentObjectExecReturn("Invalid cell range");
151
    }
152

153
    // create the containing group
154
    std::string ViewName = Label.getValue();
155
    std::stringstream result, hr, hg, hb;
156
    const App::Color& c = Color.getValue();
157
    hr << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * c.r);
158
    hg << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * c.g);
159
    hb << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * c.b);
160
    result << "<g id=\"" << ViewName << "\" transform=\"translate(" << X.getValue() << ","
161
           << Y.getValue() << ")"
162
           << " rotate(" << Rotation.getValue() << ")"
163
           << " scale(" << Scale.getValue() << ")\">" << std::endl;
164

165
    // fill the cells
166
    float rowoffset = 0.0;
167
    float coloffset = 0.0;
168
    float cellheight = 100;
169
    float cellwidth = 100;
170
    std::string celltext;
171
    Spreadsheet::Sheet* sheet = static_cast<Spreadsheet::Sheet*>(link);
172
    std::vector<std::string> skiplist;
173
    for (std::vector<std::string>::const_iterator col = columns.begin(); col != columns.end();
174
         ++col) {
175
        // create a group for each column
176
        result << "  <g id=\"" << ViewName << "_col" << (*col) << "\">" << std::endl;
177
        for (std::vector<int>::const_iterator row = rows.begin(); row != rows.end(); ++row) {
178
            // get cell size
179
            std::stringstream srow;
180
            srow << (*row);
181
            App::CellAddress address((*col) + srow.str());
182
            cellwidth = sheet->getColumnWidth(address.col());
183
            cellheight = sheet->getRowHeight(address.row());
184
            celltext = "";
185
            // get the text
186
            App::Property* prop = sheet->getPropertyByName(address.toString().c_str());
187
            std::stringstream field;
188
            if (prop) {
189
                if (prop->isDerivedFrom((App::PropertyQuantity::getClassTypeId()))) {
190
                    field << static_cast<App::PropertyQuantity*>(prop)->getValue();
191
                }
192
                else if (prop->isDerivedFrom((App::PropertyFloat::getClassTypeId()))) {
193
                    field << static_cast<App::PropertyFloat*>(prop)->getValue();
194
                }
195
                else if (prop->isDerivedFrom((App::PropertyString::getClassTypeId()))) {
196
                    field << static_cast<App::PropertyString*>(prop)->getValue();
197
                }
198
                else {
199
                    assert(0);
200
                }
201
                celltext = field.str();
202
            }
203
            // get colors, style, alignment and span
204
            int alignment = 0;
205
            std::string bcolor = "none";
206
            std::string fcolor = "#" + hr.str() + hg.str() + hb.str();
207
            std::string textstyle = "";
208
            Spreadsheet::Cell* cell = sheet->getCell(address);
209
            if (cell) {
210
                App::Color f, b;
211
                std::set<std::string> st;
212
                int colspan, rowspan;
213
                if (cell->getBackground(b)) {
214
                    std::stringstream br, bg, bb;
215
                    br << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * b.r);
216
                    bg << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * b.g);
217
                    bb << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * b.b);
218
                    bcolor = "#" + br.str() + bg.str() + bb.str();
219
                }
220
                if (cell->getForeground(f)) {
221
                    std::stringstream fr, fg, fb;
222
                    fr << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * f.r);
223
                    fg << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * f.g);
224
                    fb << std::hex << std::setfill('0') << std::setw(2) << (int)(255.0 * f.b);
225
                    fcolor = "#" + fr.str() + fg.str() + fb.str();
226
                }
227
                if (cell->getStyle(st)) {
228
                    for (std::set<std::string>::const_iterator i = st.begin(); i != st.end(); ++i) {
229
                        if ((*i) == "bold") {
230
                            textstyle = textstyle + "font-weight: bold; ";
231
                        }
232
                        else if ((*i) == "italic") {
233
                            textstyle = textstyle + "font-style: italic; ";
234
                        }
235
                        else if ((*i) == "underline") {
236
                            textstyle = textstyle + "text-decoration: underline; ";
237
                        }
238
                    }
239
                }
240
                if (cell->getSpans(rowspan, colspan)) {
241
                    for (int i = 0; i < colspan; ++i) {
242
                        for (int j = 0; j < rowspan; ++j) {
243
                            App::CellAddress nextcell(address.row() + j, address.col() + i);
244
                            if (i > 0) {
245
                                cellwidth = cellwidth + sheet->getColumnWidth(nextcell.col());
246
                            }
247
                            if (j > 0) {
248
                                cellheight = cellheight + sheet->getRowHeight(nextcell.row());
249
                            }
250
                            if ((i > 0) || (j > 0)) {
251
                                skiplist.push_back(nextcell.toString());
252
                            }
253
                        }
254
                    }
255
                }
256
                cell->getAlignment(alignment);
257
            }
258
            // skip cell if found in skiplist
259
            if (std::find(skiplist.begin(), skiplist.end(), address.toString()) == skiplist.end()) {
260
                result << "    <rect x=\"" << coloffset << "\" y=\"" << rowoffset << "\" width=\""
261
                       << cellwidth << "\" height=\"" << cellheight << "\" style=\"fill:" << bcolor
262
                       << ";stroke-width:" << LineWidth.getValue() / Scale.getValue() << ";stroke:#"
263
                       << hr.str() << hg.str() << hb.str() << ";\" />" << std::endl;
264
                if (alignment & Spreadsheet::Cell::ALIGNMENT_LEFT) {
265
                    result << "    <text style=\"" << textstyle << "\" x=\""
266
                           << coloffset + FontSize.getValue() / 2 << "\" y=\""
267
                           << rowoffset + 0.75 * cellheight << "\" font-family=\"";
268
                }
269
                if (alignment & Spreadsheet::Cell::ALIGNMENT_HCENTER) {
270
                    result << "    <text text-anchor=\"middle\" style=\"" << textstyle << "\" x=\""
271
                           << coloffset + cellwidth / 2 << "\" y=\""
272
                           << rowoffset + 0.75 * cellheight << "\" font-family=\"";
273
                }
274
                if (alignment & Spreadsheet::Cell::ALIGNMENT_RIGHT) {
275
                    result << "    <text text-anchor=\"end\" style=\"" << textstyle << "\" x=\""
276
                           << coloffset + (cellwidth - FontSize.getValue() / 2) << "\" y=\""
277
                           << rowoffset + 0.75 * cellheight << "\" font-family=\"";
278
                }
279
                result << Font.getValue() << "\""
280
                       << " font-size=\"" << FontSize.getValue() << "\""
281
                       << " fill=\"" << fcolor << "\">" << celltext << "</text>" << std::endl;
282
            }
283
            rowoffset = rowoffset + cellheight;
284
        }
285
        result << "  </g>" << std::endl;
286
        rowoffset = 0.0;
287
        coloffset = coloffset + cellwidth;
288
    }
289

290
    // close the containing group
291
    result << "</g>" << std::endl;
292

293
    // Apply the resulting fragment
294
    ViewResult.setValue(result.str().c_str());
295

296
    return App::DocumentObject::StdReturn;
297
}
298

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.