// -*- mode: c++; c-file-style: "linux"; c-basic-offset: 2; indent-tabs-mode: nil -*- // // Copyright (C) 2004-2015 Andrej Vodopivec // (C) 2014-2016 Gunter Königsmann // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program 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 General Public License for more details. // // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // /*! \file This file defines the class SumCell SumCell is the MathCell type that represents maxima's sum(), lsum and product() commands. */ #include "SumCell.h" #include "TextCell.h" #define SUM_SIGN "\x58" #define PROD_SIGN "\x59" #define SUM_DEC 2 SumCell::SumCell() : MathCell() { m_base = NULL; m_under = NULL; m_over = NULL; m_signSize = 50; m_signTop = (2* m_signSize) / 5; m_signWidth = 30; m_signWCenter = 15; m_sumStyle = SM_SUM; } SumCell::~SumCell() { if (m_base != NULL) delete m_base; if (m_under != NULL) delete m_under; if (m_over != NULL) delete m_over; if (m_next != NULL) delete m_next; } void SumCell::SetParent(MathCell *parent) { m_group=parent; if (m_base != NULL) m_base->SetParentList(parent); if (m_under != NULL) m_under->SetParentList(parent); if (m_over != NULL) m_over->SetParentList(parent); } MathCell* SumCell::Copy() { SumCell *tmp = new SumCell; CopyData(this, tmp); tmp->SetBase(m_base->CopyList()); tmp->SetUnder(m_under->CopyList()); tmp->SetOver(m_over->CopyList()); tmp->m_sumStyle = m_sumStyle; return tmp; } void SumCell::Destroy() { if (m_base != NULL) delete m_base; if (m_under != NULL) delete m_under; if (m_over != NULL) delete m_over; m_next = NULL; m_base = NULL; m_under = NULL; m_over = NULL; } void SumCell::SetOver(MathCell* over) { if (over == NULL) return ; if (m_over != NULL) delete m_over; m_over = over; } void SumCell::SetBase(MathCell* base) { if (base == NULL) return ; if (m_base != NULL) delete m_base; m_base = base; } void SumCell::SetUnder(MathCell *under) { if (under == NULL) return ; if (m_under != NULL) delete m_under; m_under = under; } void SumCell::RecalculateWidths(int fontsize) { Configuration *configuration = Configuration::Get(); double scale = configuration->GetScale(); m_signSize = SCALE_PX(50, scale); m_signWidth = SCALE_PX(30, scale); m_signWCenter = SCALE_PX(15, scale); m_base->RecalculateWidthsList(fontsize); m_under->RecalculateWidthsList(MAX(MC_MIN_SIZE, fontsize - SUM_DEC)); if (m_over == NULL) m_over = new TextCell; m_over->RecalculateWidthsList(MAX(MC_MIN_SIZE, fontsize - SUM_DEC)); if (configuration->CheckTeXFonts()) { wxDC& dc = configuration->GetDC(); int fontsize1 = (int) ((fontsize * 1.5 * scale + 0.5)); wxFont font(fontsize1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, configuration->GetTeXCMEX()); font.SetPointSize(fontsize1); dc.SetFont(font); dc.GetTextExtent(m_sumStyle == SM_SUM ? wxT(SUM_SIGN) : wxT(PROD_SIGN), &m_signWidth, &m_signSize); m_signWCenter = m_signWidth / 2; m_signTop = (2* m_signSize) / 5; m_signSize = (2 * m_signSize) / 5; } m_signWCenter = MAX(m_signWCenter, m_under->GetFullWidth(scale) / 2); m_signWCenter = MAX(m_signWCenter, m_over->GetFullWidth(scale) / 2); m_width = 2 * m_signWCenter + m_base->GetFullWidth(scale) + SCALE_PX(4, scale); ResetData(); } void SumCell::RecalculateHeight(int fontsize) { Configuration *configuration = Configuration::Get(); double scale = configuration->GetScale(); m_under->RecalculateHeightList(MAX(MC_MIN_SIZE, fontsize - SUM_DEC)); m_over->RecalculateHeightList(MAX(MC_MIN_SIZE, fontsize - SUM_DEC)); m_base->RecalculateHeightList(fontsize); m_center = MAX(m_over->GetMaxHeight() + SCALE_PX(4, scale) + m_signSize / 2, m_base->GetMaxCenter()); m_height = m_center + MAX(m_under->GetMaxHeight() + SCALE_PX(4, scale) + m_signSize / 2, m_base->GetMaxDrop()); } void SumCell::Draw(wxPoint point, int fontsize) { if (DrawThisCell(point)) { Configuration *configuration = Configuration::Get(); wxDC& dc = configuration->GetDC(); double scale = configuration->GetScale(); wxPoint base(point), under(point), over(point), sign(point); under.x += m_signWCenter - m_under->GetFullWidth(scale) / 2; under.y = point.y + m_signSize / 2 + m_under->GetMaxCenter() + SCALE_PX(2, scale); m_under->DrawList(under, MAX(MC_MIN_SIZE, fontsize - SUM_DEC)); over.x += m_signWCenter - m_over->GetFullWidth(scale) / 2; over.y = point.y - m_signSize / 2 - m_over->GetMaxDrop() - SCALE_PX(2, scale); m_over->DrawList(over, MAX(MC_MIN_SIZE, fontsize - SUM_DEC)); if (configuration->CheckTeXFonts()) { SetForeground(); int fontsize1 = (int) ((fontsize * 1.5 * scale + 0.5)); wxFont font(fontsize1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, configuration->GetTeXCMEX()); font.SetPointSize(fontsize1); dc.SetFont(font); dc.DrawText(m_sumStyle == SM_SUM ? wxT(SUM_SIGN) : wxT(PROD_SIGN), sign.x + m_signWCenter - m_signWidth / 2, sign.y - m_signTop); } else { SetPen(); if (m_sumStyle == SM_SUM) { //DRAW SUM SIGN // Upper part dc.DrawLine(point.x + m_signWCenter + m_signWidth / 6, point.y, point.x + m_signWCenter - m_signWidth / 2, point.y - m_signSize / 2 + 1); dc.DrawLine(point.x + m_signWCenter - m_signWidth / 2, point.y - m_signSize / 2, point.x + m_signWCenter + m_signWidth / 2, point.y - m_signSize / 2); dc.DrawLine(point.x + m_signWCenter - m_signWidth / 2, point.y - m_signSize / 2 + 1, point.x + m_signWCenter + m_signWidth / 2, point.y - m_signSize / 2 + 1); dc.DrawLine(point.x + m_signWCenter + m_signWidth / 2, point.y - m_signSize / 2, point.x + m_signWCenter + m_signWidth / 2, point.y - m_signSize / 2 + SCALE_PX(5, scale)); // Lower part dc.DrawLine(point.x + m_signWCenter + m_signWidth / 6, point.y, point.x + m_signWCenter - m_signWidth / 2, point.y + m_signSize / 2 - 1); dc.DrawLine(point.x + m_signWCenter - m_signWidth / 2, point.y + m_signSize / 2, point.x + m_signWCenter + m_signWidth / 2, point.y + m_signSize / 2); dc.DrawLine(point.x + m_signWCenter - m_signWidth / 2, point.y + m_signSize / 2 - 1, point.x + m_signWCenter + m_signWidth / 2, point.y + m_signSize / 2 - 1); dc.DrawLine(point.x + m_signWCenter + m_signWidth / 2, point.y + m_signSize / 2, point.x + m_signWCenter + m_signWidth / 2, point.y + m_signSize / 2 - SCALE_PX(5, scale)); } else { // DRAW PRODUCT SIGN // Vertical lines dc.DrawLine(point.x + m_signWCenter + m_signWidth / 6, point.y + m_signSize / 2, point.x + m_signWCenter + m_signWidth / 6, point.y - m_signSize / 2 + SCALE_PX(4, scale)); dc.DrawLine(point.x + m_signWCenter - m_signWidth / 6, point.y + m_signSize / 2, point.x + m_signWCenter - m_signWidth / 6, point.y - m_signSize / 2 + SCALE_PX(4, scale)); // Horizonral line (double) dc.DrawLine(point.x + m_signWCenter - m_signWidth / 2, point.y - m_signSize / 2, point.x + m_signWCenter + m_signWidth / 2, point.y - m_signSize / 2); dc.DrawLine(point.x + m_signWCenter - m_signWidth / 2, point.y - m_signSize / 2 + 1, point.x + m_signWCenter + m_signWidth / 2, point.y - m_signSize / 2 + 1); // Ticks on horizontal line dc.DrawLine(point.x + m_signWCenter - m_signWidth / 2, point.y - m_signSize / 2, point.x + m_signWCenter - m_signWidth / 2, point.y - m_signSize / 2 + SCALE_PX(5, scale)); dc.DrawLine(point.x + m_signWCenter + m_signWidth / 2, point.y - m_signSize / 2, point.x + m_signWCenter + m_signWidth / 2, point.y - m_signSize / 2 + SCALE_PX(5, scale)); } UnsetPen(); } base.x += (2 * m_signWCenter + SCALE_PX(4, scale)); m_base->DrawList(base, fontsize); } MathCell::Draw(point, fontsize); } wxString SumCell::ToString() { wxString s; if (m_sumStyle == SM_SUM) s = wxT("sum("); else s = wxT("product("); s += m_base->ListToString(); MathCell* tmp = m_under; wxString var = tmp->ToString(); wxString from; tmp = tmp->m_next; if (tmp != NULL) { tmp = tmp->m_next; if (tmp != NULL) from = tmp->ListToString(); } wxString to = m_over->ListToString(); s += wxT(",") + var + wxT(",") + from; if (to != wxEmptyString) s += wxT(",") + to + wxT(")"); else s = wxT("l") + s + wxT(")"); return s; } wxString SumCell::ToTeX() { wxString s; if (m_sumStyle == SM_SUM) s = wxT("\\sum"); else s = wxT("\\prod"); s += wxT("_{") + m_under->ListToTeX() + wxT("}"); wxString to = m_over->ListToTeX(); if (to.Length()) s += wxT("^{") + to + wxT("}"); s += wxT("{\\left. "); s += m_base->ListToTeX(); s += wxT("\\right.}"); return s; } wxString SumCell::ToOMML() { wxString base = m_base->ListToOMML(); wxString from; if(m_under) from = m_under->ListToOMML(); wxString to; if(m_over) to = m_over->ListToOMML(); wxString retval; retval = wxT(""); if (m_sumStyle == SM_SUM) retval += wxT("\x2211"); else retval += wxT("\x220F"); retval += wxT(""); if(from != wxEmptyString) retval += wxT("") + from + wxT(""); if(to != wxEmptyString) retval += wxT("") + to + wxT(""); retval += wxT("") + base + wxT(""); return retval; } wxString SumCell::ToXML() { wxString type(wxT("sum")); if (m_sumStyle == SM_PROD) type = wxT("prod"); else if (m_over->ListToString() == wxEmptyString) type = wxT("lsum"); return _T("") + m_under->ListToXML() + _T("") + m_over->ListToXML() + _T("") + m_base->ListToXML() + _T(""); } wxString SumCell::ToMathML() { wxString base = m_base->ListToMathML(); wxString from; if(m_under) from = m_under->ListToMathML(); wxString to; if(m_over) to = m_over->ListToMathML(); wxString retval; if (m_sumStyle == SM_SUM) { // retval = wxT(""); // if(!from.IsEmpty()) // retval += wxT("") + m_under->ListToMathML() + wxT(""); // if(!to.IsEmpty()) // retval += wxT("") + m_over->ListToMathML() + wxT(""); // retval += m_base->ListToMathML() + wxT(""); if(from.IsEmpty() && to.IsEmpty()) retval = wxT("") + base; if(from.IsEmpty() && !to.IsEmpty()) retval = wxT("") + to + wxT("") + base; if(!from.IsEmpty() && to.IsEmpty()) retval = wxT("") + from + wxT("") + base; if(!from.IsEmpty() && !to.IsEmpty()) retval = wxT("") + from + to + wxT("") + base; } else { // A product if(from.IsEmpty() && to.IsEmpty()) retval = wxT("") + base; if(from.IsEmpty() && !to.IsEmpty()) retval = wxT("") + to + wxT("") + base; if(!from.IsEmpty() && to.IsEmpty()) retval = wxT("") + from + wxT("") + base; if(!from.IsEmpty() && !to.IsEmpty()) retval = wxT("") + from + to + wxT("") + base; } return(wxT("")+retval+wxT("")); } void SumCell::SelectInner(wxRect& rect, MathCell** first, MathCell** last) { *first = NULL; *last = NULL; if (m_over->ContainsRect(rect)) m_over->SelectRect(rect, first, last); else if (m_under->ContainsRect(rect)) m_under->SelectRect(rect, first, last); else if (m_base->ContainsRect(rect)) m_base->SelectRect(rect, first, last); if (*first == NULL || *last == NULL) { *first = this; *last = this; } }