//--------------------------------------------------------------------------------------- bool LayouterFactory::compute_value_for_add_shapes_flag(ImoContentObj* pItem, bool fInheritedValue) { //children of main content block always add shapes ImoObj* pParent = pItem->get_parent_imo(); if (pParent->is_content() && pParent->get_parent_imo()->is_document()) return true; //objects inside a table cell never add shapes. Table cell shapes wiil //be added when the table row is fully laid out. if (pParent->is_table_cell()) return false; //otherwise inherit from parent return fInheritedValue; }
//--------------------------------------------------------------------------------------- DocCursorState CaretPositioner::click_point_to_cursor_state(GraphicModel* pGModel, int iPage, LUnits x, LUnits y, ImoObj* pImo, GmoObj* pGmo) { ImoObj* pTopImo = pImo->find_block_level_parent(); if (pTopImo->is_score()) { InnerLevelCaretPositioner* p = new_positioner(pTopImo, pGModel); SpElementCursorState innerState = p->click_point_to_cursor_state(iPage, x, y, pImo, pGmo); int topId = (innerState.get() == NULL ? k_no_imoid : pTopImo->get_id()); return DocCursorState(topId, innerState); } else return DocCursorState(pTopImo->get_id(), SharedPtr<ElementCursorState>()); }
//--------------------------------------------------------------------------------------- void SelectionSet::add_gmo(GmoObj* pGmo, bool fSaveImoId) { ensure_set_is_valid(); m_gmos.push_back(pGmo); ImoObj* pImo = pGmo->get_creator_imo(); if (pImo) { m_imos.push_back(pImo); if (fSaveImoId) m_ids.push_back( pImo->get_id() ); if (pImo->is_staffobj()) add_staffobj_to_collection( static_cast<ImoStaffObj*>(pImo) ); } }
//--------------------------------------------------------------------------------------- bool SelectionValidator::is_valid_to_add_tuplet(SelectionSet* pSelection) { //Checks if current selection is valid for adding a tuplet. //Conditions to be valid: // 1. All notes/rest in the seleccion are not in a tuplet, are consecutive, and are // in the same voice. bool fValid = true; ImoNoteRest* pStart = NULL; int nNumNotes = 0; int nVoice; ColStaffObjs* pCollection = pSelection->get_staffobjs_collection(); if (pCollection == NULL) return false; ColStaffObjsIterator it; for (it = pCollection->begin(); fValid && it != pCollection->end(); ++it) { ImoObj* pImo = (*it)->imo_object(); if (pImo->is_note_rest()) { nNumNotes++; ImoNoteRest* pNote = static_cast<ImoNoteRest*>(pImo); if (pNote->is_in_tuplet()) return false; if (!pStart) { //This is the first note/rest pStart = pNote; nVoice = pStart->get_voice(); } else { fValid &= nVoice == pNote->get_voice(); } } } //check that more than one note fValid &= (nNumNotes > 1); return fValid; }
//--------------------------------------------------------------------------------------- bool EventNotifier::notify_observers(SpEventInfo pEvent, Observable* target) { //returns true if event is dispatched to an observer std::list<Observer*>::iterator it; for (it = m_observers.begin(); it != m_observers.end(); ++it) { Observable* observedTarget = (*it)->target(); bool fNotify = (observedTarget == target); //bubbling phase. This observer is not observing target but might be //observing its parents if (!fNotify) { ImoObj* pImo = dynamic_cast<ImoObj*>(target); Observable* pObs = target; if (pImo && pObs) { while(pImo && pObs && pObs != observedTarget) { pObs = pImo->get_observable_parent(); pImo = dynamic_cast<ImoObj*>( pObs ); } fNotify = (pObs == observedTarget); //TODO: do notification and continue bubbling. } } if (fNotify) { LOMSE_LOG_DEBUG(Logger::k_events, "Posting event."); m_pDispatcher->post_event((*it), pEvent); // (*it)->notify(pEvent); return true; //TODO: remove 'return' when following problem is fixed: // Object receiving notification might modify the document (i.e. link // 'new problem') and this will invalidate target and all remaining // objects in m_observers (!!!!) } } LOMSE_LOG_DEBUG(Logger::k_events, "No observers. Event ignored"); return false; }
//--------------------------------------------------------------------------------------- void SelectionSet::ensure_set_is_valid() { if (!m_fValid) { if (m_pDoc) { m_gmos.clear(); m_imos.clear(); delete m_pCollection; m_pCollection = NULL; m_pMasterCollection = NULL; m_fValid = true; list<ImoId>::iterator it = m_ids.begin(); while (it != m_ids.end()) { ImoObj* pImo = m_pDoc->get_pointer_to_imo(*it); if (pImo) { m_imos.push_back(pImo); if (pImo->is_staffobj()) add_staffobj_to_collection( static_cast<ImoStaffObj*>(pImo) ); if (m_pGModel) //In some unit tests, there is no GModel { GmoObj* pGmo = m_pGModel->get_main_shape_for_imo( pImo->get_id() ); //TODO: When adding a GmoObj, its Shape Id should be saved so that // following method can be used: // GmoShape* get_shape_for_imo(ImoId imoId, ShapeId shapeId); m_gmos.push_back(pGmo); } ++it; } else it = m_ids.erase(it); } } else clear(); } }
//--------------------------------------------------------------------------------------- string SelectionSet::dump_selection() { if (this->empty()) return "No objects selected."; ensure_set_is_valid(); if (m_pDoc) { stringstream msg; list<ImoId>::iterator it; for (it = m_ids.begin(); it != m_ids.end(); ++it) { ImoObj* pImo = m_pDoc->get_pointer_to_imo(*it); msg << pImo->get_id() << ": " << pImo->get_name() << endl; } return msg.str(); } return "Error: can't access to Document!"; }
//--------------------------------------------------------------------------------------- list<ImoId> SelectionSet::filter_notes_rests() { //note/rests are returned in order ensure_set_is_valid(); list<ImoId> notes; ColStaffObjs* pCollection = get_staffobjs_collection(); if (pCollection != NULL) { ColStaffObjsIterator it; for (it = pCollection->begin(); it != pCollection->end(); ++it) { ImoObj* pImo = (*it)->imo_object(); if (pImo->is_note_rest()) notes.push_back(pImo->get_id()); } } return notes; }
//--------------------------------------------------------------------------------------- GmoRef GmoObj::get_ref() { if (this->is_box()) { ImoObj* pImo = get_creator_imo(); if (pImo) { if (this->is_box_control() || pImo->is_mouse_over_generator()) { ImoId id = pImo->get_id(); ImoId idg = 0; if (is_box_control()) { Control* pControl = static_cast<GmoBoxControl*>(this)->get_creator_control(); idg = pControl->get_control_id(); } return make_pair(id, idg); } } } return k_no_gmo_ref; }
//--------------------------------------------------------------------------------------- bool SelectionValidator::is_valid_for_toggle_stem(SelectionSet* pSelection) { //Returns TRUE if current selection is valid to toggle stems. //It is valid if there is at least a note with stem ColStaffObjs* pCollection = pSelection->get_staffobjs_collection(); if (pCollection == NULL) return false; ColStaffObjsIterator it; for (it = pCollection->begin(); it != pCollection->end(); ++it) { ImoObj* pImo = (*it)->imo_object(); if (pImo->is_note()) { ImoNote* pNote = static_cast<ImoNote*>(pImo); if (pNote->get_note_type() > k_whole && !pNote->is_in_chord() && pNote->get_stem_direction() != k_stem_none) return true; } } return false; }
//--------------------------------------------------------------------------------------- bool SelectionValidator::is_valid_for_join_beam(SelectionSet* pSelection) { //Returns TRUE if current selection is valid either: // - to create a beamed group with the selected notes, // - to join two or more beamed groups // - or to add a note to a beamed group //Conditions to be valid: // 1. All notes/rest in the seleccion are consecutive, are in the same // voice (unless in chord), and must be eighths or shorter ones. // 2. If not beamed, first note/rest must be a note // 3. If not beamed, last note/rest must be a note // 4. If beamed, all selected note/rest must not be in the same beam bool fValid = true; ImoNoteRest* pStart = NULL; int nNumNotes = 0; int nVoice; ImoNoteRest* pLast = NULL; bool fAllBeamed = true; //assume that all are beamed in the same beam ImoBeam* pCurBeam = NULL; ColStaffObjs* pCollection = pSelection->get_staffobjs_collection(); if (pCollection == NULL) return false; ColStaffObjsIterator it; for (it = pCollection->begin(); fValid && it != pCollection->end(); ++it) { ImoObj* pImo = (*it)->imo_object(); if (pImo->is_note_rest()) { nNumNotes++; if (!pStart) { //This is the first note/rest. If not beamed, it must be a note //shorter than quarter pStart = static_cast<ImoNoteRest*>(pImo); nVoice = pStart->get_voice(); if (!pStart->is_beamed()) { fValid &= pStart->is_note(); fValid &= static_cast<ImoNote*>(pStart)->get_note_type() >= k_eighth; fAllBeamed = false; } else pCurBeam = pStart->get_beam(); } else { // verify voice, and that it is an eighth or shorter pLast = static_cast<ImoNoteRest*>(pImo); fValid &= pLast->get_note_type() >= k_eighth; fValid &= nVoice == pLast->get_voice() || (pLast->is_note() && static_cast<ImoNote*>(pLast)->is_in_chord()); //verify that if beamed, all selected note/rest must not be in the same beam fAllBeamed &= pLast->is_beamed(); if (fValid && fAllBeamed) fAllBeamed &= (pCurBeam == pLast->get_beam()); } } } //verify last note/rest. If not beamed, it must be a note if (pLast && !pLast->is_beamed()) fValid &= pLast->is_note(); return fValid && !fAllBeamed && nNumNotes > 1; }