File indexing completed on 2024-05-26 04:34:13
0001 /* 0002 * SPDX-FileCopyrightText: 2022 Agata Cacko <cacko.azh@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 #include "KisSprayShapeOptionModel.h" 0007 0008 #include <KisLager.h> 0009 #include <klocalizedstring.h> 0010 0011 namespace { 0012 0013 auto makeSizePack = lager::lenses::getset( 0014 /** 0015 * In SizePack we use a two-stage approach in calculation of the 0016 * particles size. First we unpack the size into a special structure 0017 * that stores both, pixel and proportional sizes of the particles. 0018 * This way we are able to toggle the `proportional` switch without 0019 * invalidating existing value. 0020 * 0021 * Please note that we connect to `KisSprayShapeOptionData` as a whole 0022 * instead of its members to avoid partial updates when we change the 0023 * `proportional` value. 0024 * 0025 * Theoretically, we could use only one stage, but that would make the 0026 * code a bit more complicated. 0027 * 0028 */ 0029 [](const std::tuple<KisSprayShapeOptionData, int, qreal> &value) -> SprayShapeSizePack { 0030 auto [optionData, diameter, scale] = value; 0031 0032 SprayShapeSizePack pack; 0033 pack.isProportional = optionData.proportional; 0034 0035 if (optionData.proportional) { 0036 pack.pxSize = optionData.size * qreal(diameter) * scale / 100.0; 0037 pack.proportionalSize = optionData.size; 0038 } else { 0039 pack.pxSize = optionData.size; 0040 pack.proportionalSize = optionData.size * 100.0 / (qreal(diameter) * scale); 0041 } 0042 pack.diameter = diameter; 0043 pack.scale = scale; 0044 0045 return pack; 0046 }, 0047 [] (std::tuple<KisSprayShapeOptionData, int, qreal> value, const SprayShapeSizePack &pack) -> std::tuple<KisSprayShapeOptionData, int, qreal> { 0048 auto [optionData, diameter, scale] = value; 0049 0050 optionData.size = pack.isProportional ? pack.proportionalSize : pack.pxSize; 0051 optionData.proportional = pack.isProportional; 0052 0053 return std::make_tuple(optionData, 0054 diameter, 0055 scale); 0056 } 0057 ); 0058 0059 auto calcEffectiveSize = lager::lenses::getset( 0060 [](const SprayShapeSizePack &pack) -> QSize { 0061 return pack.isProportional ? pack.proportionalSize : pack.pxSize; 0062 }, 0063 [] (SprayShapeSizePack pack, const QSize &size) -> SprayShapeSizePack { 0064 if (pack.isProportional) { 0065 pack.proportionalSize = size; 0066 pack.pxSize = size * pack.diameter * pack.scale / 100.0; 0067 } else { 0068 pack.proportionalSize = size * 100.0 / (pack.diameter * pack.scale); 0069 pack.pxSize = size; 0070 } 0071 return pack; 0072 } 0073 ); 0074 } 0075 0076 KisSprayShapeOptionModel::KisSprayShapeOptionModel(lager::cursor<KisSprayShapeOptionData> _optionData, lager::cursor<int> diameter, lager::cursor<qreal> scale) 0077 : optionData(_optionData) 0078 , sizePack {lager::with( 0079 _optionData, 0080 diameter, 0081 scale 0082 ).zoom(makeSizePack)} 0083 , LAGER_QT(shape) {_optionData[&KisSprayShapeOptionData::shape].zoom(kislager::lenses::do_static_cast<quint8, int>)} 0084 , LAGER_QT(effectiveSize) {sizePack.zoom(calcEffectiveSize)} 0085 , LAGER_QT(effectiveProportional) {sizePack[&SprayShapeSizePack::isProportional]} 0086 , LAGER_QT(enabled) {_optionData[&KisSprayShapeOptionData::enabled]} 0087 , LAGER_QT(imageUrl) {_optionData[&KisSprayShapeOptionData::imageUrl]} 0088 , LAGER_QT(sizeSuffix) { sizePack[&SprayShapeSizePack::isProportional].map([] (bool isProportional) { return isProportional ? i18n("%") : i18n(" px"); } ) } 0089 { 0090 }