/*************************************************************************** * Copyright (c) Yorik van Havre (yorik@uncreated.net) 2015 * * Copyright (c) 2016 WandererFan (wandererfan@gmail.com) * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include #endif #include #include #include #include #include #include #include #include #include #include "DrawViewSpreadsheet.h" #include #include using namespace TechDraw; using namespace std; //=========================================================================== // DrawViewSpreadsheet //=========================================================================== PROPERTY_SOURCE(TechDraw::DrawViewSpreadsheet, TechDraw::DrawViewSymbol) DrawViewSpreadsheet::DrawViewSpreadsheet(void) { static const char *vgroup = "Spreadsheet"; Base::Reference hGrp = App::GetApplication().GetUserParameter() .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Labels"); std::string fontName = hGrp->GetASCII("LabelFont", "osifont"); ADD_PROPERTY_TYPE(Source ,(0),vgroup,App::Prop_None,"Spreadsheet to view"); Source.setScope(App::LinkScope::Global); ADD_PROPERTY_TYPE(CellStart ,("A1"),vgroup,App::Prop_None,"The top left cell of the range to display"); ADD_PROPERTY_TYPE(CellEnd ,("B2"),vgroup,App::Prop_None,"The bottom right cell of the range to display"); ADD_PROPERTY_TYPE(Font ,((fontName.c_str())),vgroup,App::Prop_None,"The name of the font to use"); ADD_PROPERTY_TYPE(TextColor,(0.0f,0.0f,0.0f),vgroup,App::Prop_None,"The default color of the text and lines"); ADD_PROPERTY_TYPE(TextSize,(12.0),vgroup,App::Prop_None,"The size of the text"); ADD_PROPERTY_TYPE(LineWidth,(0.35),vgroup,App::Prop_None,"The thickness of the cell lines"); EditableTexts.setStatus(App::Property::Hidden,true); } DrawViewSpreadsheet::~DrawViewSpreadsheet() { } short DrawViewSpreadsheet::mustExecute() const { short result = 0; if (!isRestoring()) { result = (Source.isTouched() || CellStart.isTouched() || CellEnd.isTouched() || Font.isTouched() || TextSize.isTouched() || TextColor.isTouched() || LineWidth.isTouched() ); } if (result) { return result; } return TechDraw::DrawView::mustExecute(); } void DrawViewSpreadsheet::onChanged(const App::Property* prop) { TechDraw::DrawView::onChanged(prop); } App::DocumentObjectExecReturn *DrawViewSpreadsheet::execute(void) { App::DocumentObject* link = Source.getValue(); std::string scellstart = CellStart.getValue(); std::string scellend = CellEnd.getValue(); if (!link) return new App::DocumentObjectExecReturn("No spreadsheet linked"); if (!link->getTypeId().isDerivedFrom(Spreadsheet::Sheet::getClassTypeId())) return new App::DocumentObjectExecReturn("The linked object is not a spreadsheet"); if ( (scellstart.empty()) || (scellend.empty()) ) return new App::DocumentObjectExecReturn("Empty cell value"); Symbol.setValue(getSheetImage()); return TechDraw::DrawView::execute(); } std::vector DrawViewSpreadsheet::getAvailColumns(void) { // build a list of available columns: A, B, C, ... AA, AB, ... ZY, ZZ. std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; std::vector availcolumns; for (int i=0; i<26; ++i) { //A:Z std::stringstream s; s << alphabet[i]; availcolumns.push_back(s.str()); } for (int i=0; i<26; ++i) { //AA:ZZ for (int j=0; j<26; ++j) { std::stringstream s; s << alphabet[i] << alphabet[j]; availcolumns.push_back(s.str()); } } return availcolumns; } std::string DrawViewSpreadsheet::getSVGHead(void) { std::string head = std::string("\n"); return head; } std::string DrawViewSpreadsheet::getSVGTail(void) { std::string tail = "\n"; return tail; } std::string DrawViewSpreadsheet::getSheetImage(void) { std::stringstream result; App::DocumentObject* link = Source.getValue(); link->recomputeFeature(); //make sure s/s is up to date std::string scellstart = CellStart.getValue(); std::string scellend = CellEnd.getValue(); std::vector availcolumns = getAvailColumns(); // build rows range and columns range std::vector columns; std::vector rows; //break startcell into row & column parts //Note: could do this with regex ([A-Z]*)([0-9]*) std::string startCol; int startRow = -1; for (unsigned int i=0; i= 0) { columns.push_back(startCol); rows.push_back(startRow); } else { Base::Console().Error("DVS - %s - start Column (%s) is invalid\n",getNameInDocument(),startCol.c_str()); return result.str(); } //startCol is valid //break endcell contents into row & col parts std::string endCol; int endRow = -1; for (unsigned int i=0; i endCol) || (startRow > endRow) ) { Base::Console().Error("DVS - %s - cell range is invalid\n",getNameInDocument()); return result.str(); } //fill the col/row name vectors if (startCol != endCol) { int i = iStart + 1; for ( ; i < iEnd; i++) { columns.push_back(availcolumns.at(i)); } columns.push_back(endCol); } int i = startRow + 1; for (; i < endRow; i ++) { rows.push_back(i); } rows.push_back(endRow); // create the Svg code std::string ViewName = Label.getValue(); result << getSVGHead(); App::Color c = TextColor.getValue(); result << "" << endl; // fill the cells float rowoffset = 0.0; float coloffset = 0.0; float cellheight = 100; float cellwidth = 100; std::string celltext; Spreadsheet::Sheet* sheet = static_cast(link); std::vector skiplist; for (std::vector::const_iterator col = columns.begin(); col != columns.end(); ++col) { // create a group for each column result << " " << endl; for (std::vector::const_iterator row = rows.begin(); row != rows.end(); ++row) { // get cell size std::stringstream srow; srow << (*row); App::CellAddress address((*col) + srow.str()); cellwidth = sheet->getColumnWidth(address.col()); cellheight = sheet->getRowHeight(address.row()); celltext = ""; Spreadsheet::Cell* cell = sheet->getCell(address); // get the text App::Property* prop = sheet->getPropertyByName(address.toString().c_str()); std::stringstream field; if (prop != 0) { if (prop->isDerivedFrom((App::PropertyQuantity::getClassTypeId()))) { field << cell->getFormattedQuantity(); } else if (prop->isDerivedFrom((App::PropertyFloat::getClassTypeId()))) field << cell->getFormattedQuantity(); else if (prop->isDerivedFrom((App::PropertyString::getClassTypeId()))) field << static_cast(prop)->getValue(); else assert(0); celltext = field.str(); } // get colors, style, alignment and span int alignment = 0; std::string bcolor = "none"; std::string fcolor = c.asCSSString(); std::string textstyle = ""; if (cell) { App::Color f,b; std::set st; int colspan, rowspan; if (cell->getBackground(b)) { bcolor = b.asCSSString(); } if (cell->getForeground(f)) { fcolor = f.asCSSString(); } if (cell->getStyle(st)) { for (std::set::const_iterator i = st.begin(); i != st.end(); ++i) { if ((*i) == "bold") textstyle = textstyle + "font-weight: bold; "; else if ((*i) == "italic") textstyle = textstyle + "font-style: italic; "; else if ((*i) == "underline") textstyle = textstyle + "text-decoration: underline; "; } } if (cell->getSpans(rowspan,colspan)) { for (int i=0; i 0) cellwidth = cellwidth + sheet->getColumnWidth(nextcell.col()); if (j > 0) cellheight = cellheight + sheet->getRowHeight(nextcell.row()); if ( (i > 0) || (j > 0) ) skiplist.push_back(nextcell.toString()); } } } cell->getAlignment(alignment); } // skip cell if found in skiplist if (std::find(skiplist.begin(), skiplist.end(), address.toString()) == skiplist.end()) { result << " " << endl; if (alignment & Spreadsheet::Cell::ALIGNMENT_LEFT) result << " " << celltext << "" << endl; } } rowoffset = rowoffset + cellheight; } result << " " << endl; rowoffset = 0.0; coloffset = coloffset + cellwidth; } // close the containing group result << "" << endl; result << getSVGTail(); return result.str(); } int DrawViewSpreadsheet::colInList(const std::vector& list, const std::string& toFind) { int result = -1; auto match = std::find(std::begin(list), std::end(list), toFind); if (match != std::end(list)) { result = match - std::begin(list); } return result; } // Python Drawing feature --------------------------------------------------------- namespace App { /// @cond DOXERR PROPERTY_SOURCE_TEMPLATE(TechDraw::DrawViewSpreadsheetPython, TechDraw::DrawViewSpreadsheet) template<> const char* TechDraw::DrawViewSpreadsheetPython::getViewProviderName(void) const { return "TechDrawGui::ViewProviderSpreadsheet"; } /// @endcond // explicit template instantiation template class TechDrawExport FeaturePythonT; }