gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

listitem.cpp (5371B)


      1 #include "listitem.h"
      2 
      3 #include "listmodel.h"
      4 #include "patchmanager.h"
      5 #include "savepatchdesc.h"
      6 
      7 #include "synthLib/buildconfig.h"
      8 
      9 #include "../pluginEditor.h"
     10 
     11 namespace jucePluginEditorLib::patchManager
     12 {
     13 	// Juce is funny:
     14 	// Having mouse clicks enabled prevents the list from getting mouse events, i.e. list entry selection is broken.
     15 	// However, by disabling mouse clicks, we also disable the ability to D&D onto these entries, even though D&D are not clicks...
     16 	// We solve both by overwriting hitTest() and return true as long as a D&D is in progress, false otherwise
     17 
     18 	ListItem::ListItem(ListModel& _list, const int _row) : m_list(_list), m_row(_row)
     19 	{
     20 //		setInterceptsMouseClicks(false, false);
     21 	}
     22 
     23 	void ListItem::paint(juce::Graphics& g)
     24 	{
     25 		Component::paint(g);
     26 
     27 		g.setColour(juce::Colour(0xff00ff00));
     28 
     29 		if(m_drag == DragType::Above || m_drag == DragType::Over)
     30 			g.drawRect(0, 0, getWidth(), 3, 3);
     31 		if(m_drag == DragType::Below || m_drag == DragType::Over)
     32 			g.drawRect(0, getHeight()-3, getWidth(), 3, 3);
     33 		if(m_drag == DragType::Over)
     34 		{
     35 			g.drawRect(0, 0, 3, getHeight(), 3);
     36 			g.drawRect(getWidth() - 3, 0, 3, getHeight(), 3);
     37 		}
     38 	}
     39 
     40 	void ListItem::itemDragEnter(const SourceDetails& dragSourceDetails)
     41 	{
     42 		DragAndDropTarget::itemDragEnter(dragSourceDetails);
     43 		updateDragTypeFromPosition(dragSourceDetails);
     44 	}
     45 
     46 	void ListItem::itemDragExit(const SourceDetails& dragSourceDetails)
     47 	{
     48 		DragAndDropTarget::itemDragExit(dragSourceDetails);
     49 		m_drag = DragType::Off;
     50 		repaint();
     51 	}
     52 
     53 	void ListItem::itemDragMove(const SourceDetails& dragSourceDetails)
     54 	{
     55 		updateDragTypeFromPosition(dragSourceDetails);
     56 	}
     57 
     58 	bool ListItem::isInterestedInDragSource(const SourceDetails& dragSourceDetails)
     59 	{
     60 		if(m_list.getSourceType() != pluginLib::patchDB::SourceType::LocalStorage)
     61 			return false;
     62 
     63 		const auto* list = dynamic_cast<const ListModel*>(dragSourceDetails.sourceComponent.get());
     64 
     65 		if(list && list == &m_list && m_list.canReorderPatches())
     66 			return true;
     67 
     68 		const auto* savePatchDesc = SavePatchDesc::fromDragSource(dragSourceDetails);
     69 
     70 		if(!savePatchDesc)
     71 			return false;
     72 		return true;
     73 	}
     74 
     75 	void ListItem::itemDropped(const SourceDetails& dragSourceDetails)
     76 	{
     77 		if(m_drag == DragType::Off)
     78 			return;
     79 
     80 		auto& pm = m_list.getPatchManager();
     81 
     82 		const auto drag = m_drag;
     83 		m_drag = DragType::Off;
     84 
     85 		repaint();
     86 
     87 		const auto row = drag == DragType::Above ? m_row : m_row + 1;
     88 
     89 		const auto patches = SavePatchDesc::getPatchesFromDragSource(dragSourceDetails);
     90 
     91 		if(patches.empty())
     92 			return;
     93 
     94 		const auto* savePatchDesc = SavePatchDesc::fromDragSource(dragSourceDetails);
     95 		assert(savePatchDesc);
     96 
     97 		if(dynamic_cast<const ListModel*>(dragSourceDetails.sourceComponent.get()))
     98 		{
     99 			if(!patches.empty() && pm.movePatchesTo(row, patches))
    100 				m_list.refreshContent();
    101 		}
    102 		else if(patches.size() == 1 && savePatchDesc->isPartValid())
    103 		{
    104 			const auto& source = m_list.getDataSource();
    105 			if(!source)
    106 				return;
    107 
    108 			if(drag == DragType::Over)
    109 			{
    110 				repaint();
    111 
    112 				const auto existingPatch = m_list.getPatch(m_row);
    113 
    114 				if(existingPatch)
    115 				{
    116 					genericUI::MessageBox::showYesNo(juce::MessageBoxIconType::QuestionIcon,
    117 						"Replace Patch", 
    118 						"Do you want to replace the existing patch '" + existingPatch->name + "' with contents of part " + std::to_string(savePatchDesc->getPart() + 1) + "?", 
    119 						[this, existingPatch, patches](genericUI::MessageBox::Result _result)
    120 						{
    121 							if (_result == genericUI::MessageBox::Result::Yes)
    122 							{
    123 								m_list.getPatchManager().replacePatch(existingPatch, patches.front());
    124 							}
    125 						});
    126 					return;
    127 				}
    128 			}
    129 
    130 #if SYNTHLIB_DEMO_MODE
    131 			pm.getEditor().showDemoRestrictionMessageBox();
    132 #else
    133 			const auto part = savePatchDesc->getPart();
    134 
    135 			pm.copyPatchesTo(source, patches, row, [this, part](const std::vector<pluginLib::patchDB::PatchPtr>& _patches)
    136 			{
    137 				juce::MessageManager::callAsync([this, part, _patches]
    138 				{
    139 					m_list.getPatchManager().setSelectedPatch(part, _patches.front());
    140 				});
    141 			});
    142 #endif
    143 
    144 			repaint();
    145 		}
    146 
    147 	}
    148 
    149 	void ListItem::mouseDown(const juce::MouseEvent& event)
    150 	{
    151 //		m_list.mouseDown(event);
    152 	}
    153 
    154 	bool ListItem::hitTest(int x, int y)
    155 	{
    156 		if (const juce::DragAndDropContainer* container = juce::DragAndDropContainer::findParentDragContainerFor(this))
    157 		{
    158 			if (container->isDragAndDropActive())
    159 				return true;
    160 		}
    161 
    162 		return false;
    163 	}
    164 
    165 	void ListItem::updateDragTypeFromPosition(const SourceDetails& dragSourceDetails)
    166 	{
    167 		const auto prev = m_drag;
    168 
    169 		const auto* list = dynamic_cast<const ListModel*>(dragSourceDetails.sourceComponent.get());
    170 
    171 		if(list && list == &m_list)
    172 		{
    173 			// list is being sorted
    174 			if (dragSourceDetails.localPosition.y < (getHeight() >> 1))
    175 				m_drag = DragType::Above;
    176 			else
    177 				m_drag = DragType::Below;
    178 		}
    179 		else
    180 		{
    181 			const auto* savePatchDesc = SavePatchDesc::fromDragSource(dragSourceDetails);
    182 
    183 			if(savePatchDesc)
    184 			{
    185 				// a patch wants to be saved
    186 
    187 				if(m_list.hasFilters())
    188 				{
    189 					// only allow to replace
    190 					m_drag = DragType::Over;
    191 				}
    192 				else
    193 				{
    194 					if (dragSourceDetails.localPosition.y < (getHeight() / 3))
    195 						m_drag = DragType::Above;
    196 					else if (dragSourceDetails.localPosition.y >= (getHeight() * 2 / 3))
    197 						m_drag = DragType::Below;
    198 					else
    199 						m_drag = DragType::Over;
    200 				}
    201 			}
    202 		}
    203 
    204 		if (prev != m_drag)
    205 			repaint();
    206 	}
    207 }