Пример #1
0
void DocHistory::OnMouseLeftDown(wxMouseEvent& event) {
	const int y = event.GetY() + m_scrollPos;

	// Which node are we over?
	int node_id = -1;
	for (unsigned int i = 0; i < m_items.size(); ++i) {
		const int node_ypos = m_items[i].ypos;
		if (y >= node_ypos && y < (node_ypos + m_lineHeight)) {
			node_id = i;
			break;
		}
	}

	if (node_id != -1) {
		// We do not have to set the document now. We will recieve
		// a WIN_CHANGEDOC notifer if the documents actually gets
		// set on a page.

		// Do not return a reference. The events might modify
		// m_items underneath it.
		const doc_id hot_doc = m_items[node_id].doc;

		if (hot_doc.IsDraft()) {
			doc_id draft_head;
			cxLOCK_READ(m_catalyst)
				draft_head = catalyst.GetDraftHead(hot_doc.document_id);
			cxENDLOCK
			m_dispatcher.Notify(wxT("WIN_SETDOCUMENT"), &draft_head, m_source_win_id);
		}
		else m_dispatcher.Notify(wxT("WIN_SETDOCUMENT"), &hot_doc, m_source_win_id);
	}
}
Пример #2
0
void DocHistory::SetDocument(const doc_id& di) {
	//wxASSERT(m_catalyst.IsOk(di));

	// Check if we are invalidating the view
	if (!di.IsOk()) {
		Clear();
		return;
	}

	if (m_sourceDoc != di) {
		cxLOCKDOC_WRITE(m_doc)
			doc.SetDocument(di);

			// Get the document
			m_document_id = di.IsDraft() ? doc.GetParent().document_id : di.document_id;
		cxENDLOCK

		m_sourceDoc = di;

		// Check if we need to rebuild the tree
		ReBuildTree();
	}

	Select(m_selectedNode);
	MakeItemVisible(m_selectedNode);
}
Пример #3
0
void DocHistory::OnVersionTreeSel(VersionTreeEvent& event) {
	wxASSERT(event.GetItem() >= 0 && event.GetItem() < m_items.size());

	// Do not return a reference. The events might modify
	// m_items underneath it.
	const doc_id hot_doc = m_items[event.GetItem()].doc;

	// We do not have to set the document now. We will recieve
	// a WIN_CHANGEDOC notifer if the documents actually gets
	// set on a page.

	if (hot_doc.IsDraft()) {
		doc_id draft_head;
		cxLOCK_READ(m_catalyst)
			draft_head = catalyst.GetDraftHead(hot_doc.document_id);
		cxENDLOCK
		m_dispatcher.Notify(wxT("WIN_SETDOCUMENT"), &draft_head, m_source_win_id);
	}
	else m_dispatcher.Notify(wxT("WIN_SETDOCUMENT"), &hot_doc, m_source_win_id);
}
Пример #4
0
void DocHistory::AddChildren(int parent_pos, const doc_id& di, const doc_id& sel_doc, const Catalyst& catalyst) {
	wxASSERT(di.IsDocument());

	const int childCount = catalyst.GetChildCount(di);
	for (int i = 0; i < childCount; ++i) {
		const doc_id child = catalyst.GetChildID(di, i);
		item new_item;
		new_item.doc = child;
		new_item.date = catalyst.GetDocDate(child);
		new_item.parent = parent_pos;

		// Find the insert pos
		size_t n;
		for (n = parent_pos+1; n < m_items.size(); ++n) {
			if (new_item.date < m_items[n].date) {
				m_items.insert(m_items.begin()+n, new_item);

				// The indexes under the insertion has moved, so
				// we also have to update any references to this range
				if (m_selectedNode >= (int)n) ++m_selectedNode;
				for (size_t n2 = n+1; n2 < m_items.size(); ++n2) {
					int& parent = m_items[n2].parent;
					if (parent >= (int)n) ++parent;
				}
				break;
			}
		}
		if (n == m_items.size()) {
			m_items.push_back(new_item);
		}

		// Check if this is the selected node
		if (child.IsDocument()) {
			if (child == sel_doc) m_selectedNode = n;

			AddChildren(n, child, sel_doc, catalyst);
		}
		else if (child.SameDoc(sel_doc)) m_selectedNode = n;
	}
}
Пример #5
0
void DiffLineCell::CalcLayout(const doc_id& rev1, const doc_id& rev2) {
	wxASSERT(rev1.IsOk());
	wxASSERT(rev2.IsOk());
	wxASSERT(char_width > 0);

	Clear();

	cxLOCKDOC_READ(m_doc)
		if (rev1 == rev2) { // root has itself as parent
			int length = doc.GetVersionLength(rev2);
			if (length > 0) {
				length = wxMin(length, (int)doc.GetCharPos(rev2, 0, (width/char_width)+1));
				wxString text = doc.GetTextPart(rev2, 0, length);
				CalcSubCells(text, *wxBLACK, m_insertColour);
			}
		}
		else if (!doc.TextChanged(rev1, rev2)) {
			if (doc.PropertiesChanged(rev1, rev2)) CalcSubCells(_("Properties Changed"), *wxBLACK, bgcolor);
		}
		else {
			bool change = false;
			const std::vector<match> matchlist = doc.Diff(rev1, rev2);

			unsigned int pos1 = 0;
			unsigned int pos2 = 0;

			unsigned int i = 0;
			while (i < matchlist.size()) { 
				if (line_width > width) {
					// No need to parse something that won't be drawn
					break;
				}

				// Calculate how many chars there are room for in
				// the visible part. Then we can avoid retrieving
				// long strings (which can be *very* long)
				int chars_left = ((width-line_width)/char_width)+1;

				match m = matchlist[i];
				if (pos1 < m.iv1_start_pos) { // Deleted
					unsigned int last_endpos = doc.GetCharPos(rev1, pos1, chars_left);
					CalcSubCells(doc.GetTextPart(rev1, pos1, wxMin(m.iv1_start_pos, last_endpos)), *wxBLACK, m_deleteColour); // PASTEL RED
					change = true;
				}
				if (pos2 < m.iv2_start_pos) { // Inserted
					unsigned int last_endpos = doc.GetCharPos(rev2, pos2, chars_left);
					CalcSubCells(doc.GetTextPart(rev2, pos2, wxMin(m.iv2_start_pos, last_endpos)), *wxBLACK, m_insertColour); // PASTEL GREEN
					change = true;
				}
				if (m.iv2_end_pos > 0 && m.iv2_end_pos > m.iv2_start_pos) {
					if (change) {
						unsigned int last_endpos = doc.GetCharPos(rev2, m.iv2_start_pos, chars_left);
						CalcSubCells(doc.GetTextPart(rev2, m.iv2_start_pos, wxMin(m.iv2_end_pos, last_endpos)), m_hiddenColour, bgcolor);
					}
					else {
						// Get up to 5 chars before first change
						unsigned int startpos = doc.GetCharPos(rev2, m.iv2_end_pos, -5);
						wxString initialText = doc.GetTextPart(rev2, wxMax(m.iv2_start_pos, startpos), m.iv2_end_pos);
						CalcSubCells(initialText, m_hiddenColour, bgcolor);
					}
				}

				pos1 = m.iv1_end_pos;
				pos2 = m.iv2_end_pos;

				++i;
			}
		}
	cxENDLOCK
}
Пример #6
0
void DiffLineCell::CalcLayoutRange(const doc_id& rev1, const doc_id& rev2, const interval& range) {
	wxASSERT(rev1.IsOk());
	wxASSERT(rev2.IsOk());
	wxASSERT(char_width > 0);

	Clear();

	cxLOCKDOC_READ(m_doc)
		if (rev1 == rev2) { // root has itself as parent
			// Get up to 5 chars before range
			if (range.start > 0) {
				const unsigned int startpos = doc.GetCharPos(rev2, range.start, -5);
				const wxString initialText = doc.GetTextPart(rev2, wxMax(0, startpos), range.start);
				CalcSubCells(initialText, m_hiddenColour, bgcolor);
			}

			// Get the range
			unsigned int chars_left = ((width - line_width) / char_width)+1;
			unsigned int end = wxMin(range.end, doc.GetCharPos(rev2, range.start, chars_left));
			unsigned int length = end - range.start;
			if (length == 0) return;
			const wxString text = doc.GetTextPart(rev2, range.start, length);
			CalcSubCells(text, *wxBLACK, m_insertColour);

			// Get text after range
			chars_left = ((width - line_width) / char_width)+1;
			length = doc.GetCharPos(rev2, range.end, chars_left);
			if (length == 0) return;
			const wxString text2 = doc.GetTextPart(rev2, range.start, length);
			CalcSubCells(text2, m_hiddenColour, bgcolor);
		}
		else {
			bool change = false;
			const std::vector<match> matchlist = doc.Diff(rev1, rev2);

			unsigned int pos1 = 0;
			unsigned int pos2 = 0;

			// Advance to range start (ignoring sentinel at end)
			unsigned int i = 0;
			while (i+1 < matchlist.size() && matchlist[i].iv2_end_pos < range.start) {
				pos1 = matchlist[i].iv1_end_pos;
				pos2 = matchlist[i].iv2_end_pos;
				++i;
			}

			while (i < matchlist.size()) { 
				if (line_width > width) break; // No need to parse something that won't be drawn

				// Calculate how many chars there are room for in
				// the visible part. Then we can avoid retrieving
				// long strings (which can be *very* long)
				int chars_left = ((width-line_width)/char_width)+1;

				const match& m = matchlist[i];
				if (pos1 < m.iv1_start_pos && pos2 >= range.start && pos2 <= range.end) { // Deleted (and in range)
					const unsigned int last_endpos = doc.GetCharPos(rev1, pos1, chars_left);
					CalcSubCells(doc.GetTextPart(rev1, pos1, wxMin(m.iv1_start_pos, last_endpos)), *wxBLACK, m_deleteColour); // PASTEL RED
					change = true;
				}
				if (pos2 < m.iv2_start_pos && range.start < m.iv2_start_pos) { // Inserted
					// Get text before range
					if (pos2 < range.start) {
						const unsigned int ins_start = wxMax(pos2, doc.GetCharPos(rev2, range.start, -5));
						CalcSubCells(doc.GetTextPart(rev2, ins_start, range.start), m_hiddenColour, bgcolor);
					}

					// Get text in range (only if overlap)
					if (pos2 < range.end && m.iv2_start_pos > range.start) {
						const unsigned int start_pos = wxMax(pos2, range.start);
						const unsigned int last_endpos = wxMin(wxMin(range.end, m.iv2_start_pos), doc.GetCharPos(rev2, start_pos, chars_left));
						CalcSubCells(doc.GetTextPart(rev2, start_pos, last_endpos), *wxBLACK, m_insertColour); // PASTEL GREEN
					}

					// Get text after range
					if (m.iv2_start_pos > range.end) {
						const unsigned int rest_start = wxMax(pos2, range.end);
						const unsigned int rest_end = wxMin(m.iv2_start_pos, doc.GetCharPos(rev2, rest_start, chars_left));
						CalcSubCells(doc.GetTextPart(rev2, rest_start, rest_end), m_hiddenColour, bgcolor);
					}
					
					change = true;
				}
				if (m.iv2_end_pos > 0 && m.iv2_end_pos > m.iv2_start_pos) {
					if (change) {
						const unsigned int last_endpos = doc.GetCharPos(rev2, m.iv2_start_pos, chars_left);
						CalcSubCells(doc.GetTextPart(rev2, m.iv2_start_pos, wxMin(m.iv2_end_pos, last_endpos)), m_hiddenColour, bgcolor);
					}
					else {
						// Get up to 5 chars before first change
						const unsigned int startpos = doc.GetCharPos(rev2, m.iv2_end_pos, -5);
						const wxString initialText = doc.GetTextPart(rev2, wxMax(m.iv2_start_pos, startpos), m.iv2_end_pos);
						CalcSubCells(initialText, m_hiddenColour, bgcolor);
					}
				}

				pos1 = m.iv1_end_pos;
				pos2 = m.iv2_end_pos;
				++i;
			}
		}
	cxENDLOCK
}
Пример #7
0
void RevTooltip::SetDocument(const doc_id& di, wxPoint pos) {
    Hide();

    cxLOCK_READ(m_catalyst)
    wxASSERT(catalyst.IsOk(di));

    m_docId = di;

    // Set the user info
    const unsigned int userId = catalyst.GetDocAuthor(m_docId);
    m_userPic->SetBitmap(catalyst.GetUserPic(userId));
    m_userName->SetLabel(catalyst.GetUserName(userId));
    if (userId == 0) m_userColor->Hide();
    else {
        m_userColor->SetBackgroundColour(catalyst.GetUserColor(userId));
        m_userColor->Show();
    }

    // Set the Label
    wxString label = catalyst.GetLabel(m_docId);
    if (!label.empty()) label += wxT(":");
    m_labelCtrl->SetLabel(label);

    // Set the Date
    const wxDateTime date = catalyst.GetDocDate(m_docId);
    const wxString age = catalyst.GetDocAge(m_docId);
    const wxString longdate = date.Format(wxT("%A, %B %d, %Y - %X ")) + wxString::Format(wxT("(%s)"),age.c_str());
    m_dateCtrl->SetLabel(longdate);

    // Set the Comment
    m_descCtrl->SetLabel(catalyst.GetDescription(m_docId));

    // Show paths to mirrors (if available)
    if (catalyst.IsMirrored(di)) {
        m_mainSizer->Show(m_mirrorSizer, true, true);

        wxArrayString paths;
        if (di.IsDraft()) catalyst.GetMirrorPathsForDraft(di, paths); // gets mirrors for all draft revisions
        else catalyst.GetMirrorPaths(di, paths);

        if (!paths.IsEmpty()) {
            wxString tip = paths[0];
            for (size_t i = 1; i < paths.GetCount(); ++i) {
                tip += wxT("\n");
                tip += paths[i];
            }
            m_mirrorlistCtrl->SetLabel(tip);
        }
        else wxASSERT(false);
    }
    else m_mainSizer->Show(m_mirrorSizer, false, true);
    cxENDLOCK

    m_mainSizer->Layout();
    m_mainSizer->SetSizeHints(m_mainPanel);
    m_mainSizer->SetSizeHints(this);

    // Get the size of the screen
    const int screen_x = wxSystemSettings::GetMetric(wxSYS_SCREEN_X);
    const int screen_y = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y);

    // Get the size of the mouse cursor
    // BUG WORKAROUND: GetMetric gives how large it _can_ be (32*32) not
    // how large the actual visible image is.
    const int cursor_x = 16; // wxSystemSettings::GetMetric(wxSYS_CURSOR_X);
    const int cursor_y = 17; // wxSystemSettings::GetMetric(wxSYS_CURSOR_Y);

    const wxSize size = GetSize();

    // Calculate the correct placement
    // (pos is assumed to be upper left corner of cursor)
    if (pos.x + cursor_x + size.x > screen_x) pos.x -= size.x + 3;
    else pos.x += cursor_x;

    if (pos.y + cursor_y + size.y > screen_y) pos.y -= size.y + 3;
    else pos.y += cursor_y;

    Move(pos);
    Show();
}