File indexing completed on 2024-12-22 04:13:04

0001 /*
0002  *  SPDX-FileCopyrightText: 2017 Laurent Valentin Jospin <laurent.valentin@famillejospin.ch>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_document_aware_spin_box_unit_manager.h"
0008 
0009 #include "KisPart.h"
0010 #include "KisMainWindow.h"
0011 #include "KisView.h"
0012 #include "KisDocument.h"
0013 #include "kis_types.h"
0014 #include "kis_image.h"
0015 #include "kis_image_animation_interface.h"
0016 #include "kis_time_span.h"
0017 
0018 
0019 KisSpinBoxUnitManager* KisDocumentAwareSpinBoxUnitManagerBuilder::buildUnitManager(QObject* parent)
0020 {
0021     return new KisDocumentAwareSpinBoxUnitManager(parent);
0022 }
0023 
0024 void KisDocumentAwareSpinBoxUnitManager::setDocumentAwarenessToExistingUnitSpinBox(KisDoubleParseUnitSpinBox* spinBox, bool setUnitFromOutsideToggle)
0025 {
0026     KisDocumentAwareSpinBoxUnitManager* manager = new KisDocumentAwareSpinBoxUnitManager(spinBox);
0027     spinBox->setUnitManager(manager);
0028     spinBox->setUnitChangeFromOutsideBehavior(setUnitFromOutsideToggle);
0029 }
0030 
0031 KisDoubleParseUnitSpinBox* KisDocumentAwareSpinBoxUnitManager::createUnitSpinBoxWithDocumentAwareness(QWidget* parent)
0032 {
0033     KisDoubleParseUnitSpinBox* spinBox = new KisDoubleParseUnitSpinBox(parent);
0034     setDocumentAwarenessToExistingUnitSpinBox(spinBox);
0035 
0036     return spinBox;
0037 }
0038 
0039 KisDocumentAwareSpinBoxUnitManager::KisDocumentAwareSpinBoxUnitManager(QObject *parent, int pPixDir):
0040     KisSpinBoxUnitManager(parent)
0041 {
0042     if (pPixDir == PIX_DIR_Y) {
0043         pixDir = PIX_DIR_Y;
0044     } else {
0045         pixDir = PIX_DIR_X;
0046     }
0047 
0048     grantDocumentRelativeUnits(); //the purpose of this class is to manage document relative units.
0049 }
0050 
0051 
0052 qreal KisDocumentAwareSpinBoxUnitManager::getConversionFactor(int dim, QString psymbol) const
0053 {
0054     QString symbol = psymbol;
0055 
0056     if (symbol == "%") { //percent can be seen as vw or vh depending of the reference side in the image.
0057         if (pixDir == PIX_DIR_X) {
0058             symbol = "vw";
0059         } else {
0060             symbol = "vh";
0061         }
0062     }
0063 
0064     qreal factor = KisSpinBoxUnitManager::getConversionFactor(dim, symbol);
0065 
0066     if (factor > 0) {
0067         //no errors occurred at a lower level, so the conversion factor has been get.
0068         return factor;
0069     }
0070 
0071     factor = 1; //fall back to something natural in case document is unreachable (1 px = 1 pt = 1vw = 1vh). So a virtual document of 100x100 with a resolution of 1.
0072 
0073     if (!KisPart::instance()->currentMainwindow()) {
0074         return factor;
0075     }
0076 
0077     KisView* view = KisPart::instance()->currentMainwindow()->activeView();
0078 
0079     if (view == nullptr) {
0080         return factor;
0081     }
0082 
0083     KisDocument* doc = view->document();
0084 
0085     if (doc == nullptr) {
0086         return factor;
0087     }
0088 
0089     KisImage* img = doc->image().data();
0090 
0091     if (img == nullptr) {
0092         return factor;
0093     }
0094 
0095     qreal resX = img->xRes();
0096     qreal resY = img->yRes();
0097     qreal sizeX = img->width();
0098     qreal sizeY = img->height();
0099 
0100     switch (dim) {
0101 
0102     case LENGTH:
0103         if (symbol == "px") {
0104 
0105             if (pixDir == PIX_DIR_X) {
0106                 factor = resX;
0107             } else {
0108                 factor = resY;
0109             }
0110         } else if (symbol == "vw") {
0111             qreal docWidth = sizeX/resX;
0112 
0113             factor = 100.0/docWidth; //1 vw is 1% of document width, 1 vw in point is docWidth/100 so 1 point in vw is the inverse.
0114         } else if (symbol == "vh") {
0115             qreal docHeight = sizeY/resY;
0116 
0117             factor = 100.0/docHeight;
0118         }
0119         break;
0120 
0121     case IMLENGTH:
0122 
0123         if (symbol == "vw") {
0124             factor = 100.0/sizeX; //1 vw is 1% of document width, 1 vw in pixel is sizeX/100 so 1 pixel in vw is the inverse.
0125 
0126         } else if (symbol == "vh") {
0127             factor = 100.0/sizeY;
0128         }
0129         break;
0130 
0131     case TIME:
0132     {
0133         if (symbol == "s") {
0134             qreal fps = img->animationInterface()->framerate();
0135 
0136             factor = 1/fps;
0137         } else if (symbol == "%") {
0138             const KisTimeSpan & time_range = img->animationInterface()->documentPlaybackRange();
0139             qreal n_frame = time_range.end() - time_range.start();
0140 
0141             factor = 100/n_frame;
0142         }
0143     }
0144         break;
0145 
0146     default:
0147         break;
0148 
0149     }
0150 
0151     return factor;
0152 }
0153 
0154 qreal KisDocumentAwareSpinBoxUnitManager::getConversionConstant(int dim, QString symbol) const
0155 {
0156     if (dim == TIME && symbol == "%") {
0157         KisImage* img = KisPart::instance()->currentMainwindow()->activeView()->document()->image().data();
0158         const KisTimeSpan & time_range = img->animationInterface()->documentPlaybackRange();
0159         qreal n_frame = time_range.end() - time_range.start();
0160 
0161         return -time_range.start()*100.0/n_frame;
0162     }
0163 
0164     return KisSpinBoxUnitManager::getConversionConstant(dim, symbol);
0165 }
0166 
0167 
0168 bool KisDocumentAwareSpinBoxUnitManager::hasPercent(int unitDim) const {
0169 
0170     if (unitDim == IMLENGTH || unitDim == LENGTH) {
0171         return true;
0172     }
0173 
0174     return KisSpinBoxUnitManager::hasPercent(unitDim);
0175 }