Exemple #1
0
/*----------------------------------------------------------------------------------------------
	The edit box changed. We need to validate what was done.
	@param pedit
	@return
----------------------------------------------------------------------------------------------*/
bool AfDeFeCliRef::OnChange(AfDeFeEdBoxBut::DeEdit * pedit)
{
	if (m_fRecurse)
	{
		m_fRecurse = false;
		return true;
	}
	if (!m_hwnd)
		return true; // We aren't completely set up yet, so ignore this.

	// Get the characters from the edit box.
	ITsStringPtr qtss;
	::SendMessage(m_hwnd, FW_EM_GETTEXT, 0, (LPARAM)&qtss);

	int ichMin;
	int ichLim;
	::SendMessage(m_hwnd, EM_GETSEL, (WPARAM)&ichMin, (LPARAM)&ichLim);

	int cchTyped; // number of characters in the typed string
	// JohnT: use a StrUni rather than an StrUniBuf, because some user sometime will accidentally
	// paste something long here, and performance here is not critical.
	StrUni stuTyped;
	OLECHAR * pchBuf;
	qtss->get_Length(&cchTyped);

	if (cchTyped > kcchPossNameAbbrMax)
	{
		if (ichMin == cchTyped)
			ichMin = kcchPossNameAbbrMax;
		if (ichLim == cchTyped)
			ichLim = kcchPossNameAbbrMax;
		cchTyped = kcchPossNameAbbrMax;
		m_fRecurse = true; // Stop the recursion caused by the next instruction.
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
	}

	stuTyped.SetSize(cchTyped, &pchBuf);
	qtss->FetchChars(0, cchTyped, pchBuf);

#ifdef DEBUG_THIS_FILE
	StrAnsi sta;
	sta.Format("AfDeFeCliRef::OnChange:  pedit->m_ch=%d; ichMin=%d; ichLim=%d; pedit->m_cchMatched=%d; cchTyped=%d.\n",
										 pedit->m_ch,    ichMin,    ichLim,    pedit->m_cchMatched,    cchTyped);
	OutputDebugString(sta.Chars());
#endif

	bool fTypeAhead = false; // allow type ahead only when adding characters at end of current item
							// or backspacing at end of current item.
	bool fNeedCompare;
	if (pedit->m_ch == 0) // (see kcidEditPaste special code)
	{
		// If we pasted something, force a compare.
		fNeedCompare = true;
	}
	else if (ichMin == pedit->m_cchMatched + 1 && pedit->m_ch != VK_BACK && pedit->m_ch != VK_DELETE)
	{
		// Need to compare if we typed a character and we are one greater than last match.
		fNeedCompare = true;
		if (cchTyped == ichMin)
		{
			fTypeAhead = true;
#ifdef DEBUG_THIS_FILE
			sta.Format("OnChange: 1 - setting fTypeAhead to true.\n");
			OutputDebugString(sta.Chars());
#endif
		}
	}
	else if (ichMin > pedit->m_cchMatched)
	{
		// Don't compare any other time we are past the last match.
		fNeedCompare = false;
	}
//	else if ((cchTyped == ichMin) && (ichMin == ichLim) && (pedit->m_ch != kscDelForward))
	else if ((cchTyped == ichMin) && (ichMin == ichLim) && (pedit->m_ch != 46))
	{
		// Need to compare if we typed a character and we are at the end of the item
		// Need to compare if we delete the last character in the non-type-ahead string
		fNeedCompare = true;
		fTypeAhead = true;
#ifdef DEBUG_THIS_FILE
		sta.Format("OnChange:  kscDelForward=%d.\n");
		OutputDebugString(sta.Chars());
		sta.Format("OnChange: 2 - setting fTypeAhead to true.\n");
		OutputDebugString(sta.Chars());
#endif
	}
	else
	{
		// Always compare if we are not past the last match.
		fNeedCompare = true;
	}

	int cch;

	// Since the edit box deletes the selection on backspace, we need to use
	// some extra logic to make backspace actually move the selection back.
	if (pedit->m_cchMatched && pedit->m_ch == VK_BACK && m_pss)
	{
		// If we had a previous match and we got a backspace, we always decrement the matched
		// characters and start looking at that point.
		cch = --pedit->m_cchMatched;
	}
	else
	{
		// Otherwise we start looking at the cursor location.
		cch = ichMin;
	}

	AfLpInfo * plpi = GetLpInfo();
	AssertPtr(plpi);

	PossListInfoPtr qpli;
	plpi->LoadPossList(m_hvoPssl, m_wsMagic, &qpli);
	AssertPtr(qpli);

	PossItemInfo * ppii = NULL;
	ComBool fExactMatch = false;

	fNeedCompare = true;

	if (cchTyped == 0)
	{
		// If nothing to match, get the first item in the possibility list. If we are
		// already at that item, remove the item. If we are already cleared, do nothing.
		if (!m_pss)
			return true;
		// If everything is highlighted, we want to clear the item with Del or Bsp.
		// But when we are backspacing, if there is only one character left and we backspace
		// over that, we want to switch to the first item in the list.
		ppii = qpli->GetPssFromIndex(0);
		if (ichMin != 1)
		{
			m_pss = 0;
			m_qtss = NULL;
			pedit->m_cchMatched = 0; // Keep cursor at beginning of item.
			m_fRecurse = true;
			::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)m_qtss.Ptr());
			return true;
		}
	}
	else if (fNeedCompare)
	{
		// Try to find an item that matches what the user typed in the possibility list.
		StrUni stuMatch(stuTyped);
/////		stuMatch.Replace(cch, stuMatch.Length(), L"");// Delete chars to right of cursor.
		Locale loc = GetLpInfo()->GetLocale(m_ws);
		if (m_fHier)
		{
			ppii = qpli->FindPssHier(stuMatch.Chars(), loc, m_pnt, fExactMatch);
		}
		else
		{
			ppii = qpli->FindPss(stuMatch.Chars(), loc, m_pnt);
		}

		if (ppii)
		{
			// found a match that starts with stuTyped
			int ipssTemp;

			// TODO TimP:  check for hierarchy.  If stuTyped contains hierarchy,

			// Was the match exact (rather than just starting with stuTyped) ?
			if (fExactMatch) // May have matched in the FindPssHier() call above.
			{
#ifdef DEBUG_THIS_FILE
				sta.Format("OnChange:  Exact match (hier).\n");
				OutputDebugString(sta.Chars());
#endif
			}
			else
			{
				fExactMatch = ! qpli->PossUniqueName(-1, stuTyped, m_pnt, ipssTemp);
				if (fExactMatch)
				{
#ifdef DEBUG_THIS_FILE
					sta.Format("OnChange:  Exact match.\n");
					OutputDebugString(sta.Chars());
#endif
					// in case FindPss() above matches "ABC" but "AB" is also in list.
					ppii = qpli->GetPssFromIndex(ipssTemp);
				}
				else
				{
#ifdef DEBUG_THIS_FILE
					sta.Format("OnChange:  Not exact match.\n");
					OutputDebugString(sta.Chars());
#endif
				}
			}
		}
	}
	else
		ppii = NULL;

	StrUni stuFound;
	int ws = m_ws;
	if (ppii && (fTypeAhead || fExactMatch))
	{
		// If found, process the new item.
		int pss = ppii->GetPssId();
		m_pss = pss;
		if (m_fHier)
			ppii->GetHierName(qpli, stuFound, m_pnt);
		else
			ppii->GetName(stuFound, m_pnt);
		ws = ppii->GetWs();

		// If the last character was a delimiter, we need to set cch accordingly.
		if (m_fHier && (stuTyped.Length() > 0) && (pedit->m_ch != VK_BACK) &&
			(stuTyped.GetAt(stuTyped.Length() - 1) == kchHierDelim))
		{
			// Need to set cch to the position of the last delimiter.
			cch = stuFound.FindCh(kchHierDelim, cch - 1) + 1;
		}

		pedit->m_cchMatched = cch;
	}
	else
	{
		// Something illegal was typed. Assume they are adding a new item.
		if (pedit->m_cchMatched + 1 == cch && pedit->m_ch != VK_BACK)
			::MessageBeep(MB_ICONEXCLAMATION); // Beep on the first unmatched character.
		// Underline the string with a red squiggly.
		ITsIncStrBldrPtr qtisb;
		qtisb.CreateInstance(CLSID_TsIncStrBldr);
		qtisb->SetIntPropValues(ktptWs, ktpvDefault, m_ws);
		CheckHr(qtisb->SetIntPropValues(ktptUnderColor, ktpvDefault, kclrRed));
		CheckHr(qtisb->SetIntPropValues(ktptUnderline, ktpvEnum, kuntSquiggle));
		qtisb->AppendRgch(stuTyped.Chars(), stuTyped.Length());
		qtisb->GetString(&m_qtss);
		m_fRecurse = true; // Stop the recursion caused by the next instruction.
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)m_qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
		m_pss = 0; // We no longer have a matched HVO.
		return true;
	}

	// Update the edit box text and selection.
	ITsStrFactoryPtr qtsf;
	qtsf.CreateInstance(CLSID_TsStrFactory);
	qtsf->MakeStringRgch(stuFound.Chars(), stuFound.Length(), ws, &qtss);
	m_qtss = qtss;

#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  pedit->m_cchMatched=%d; stuFound.Length()=%d; ichMin=%d; ichLim=%d.\n",
										 pedit->m_cchMatched,    stuFound.Length(),    ichMin,    ichLim);
	OutputDebugString(sta.Chars());
#endif

	m_fRecurse = true; // Shortcut the recursion caused by the next instruction.
	if (fTypeAhead)
	{
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, pedit->m_cchMatched, stuFound.Length());
#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  type ahead.\n");
	OutputDebugString(sta.Chars());
#endif
	}
	else
	{
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  NOT type ahead.\n");
	OutputDebugString(sta.Chars());
#endif
	}

	return true;
}
Exemple #2
0
/*----------------------------------------------------------------------------------------------
	Return the text string that gets shown to the user when this object needs to be displayed.
	This is the method for displaying the name of a single reference. This view shows the
	name for an RnGenericRec consisting of the type of record, hyphen, title, hyphen,
	creation date. "Subevent - Fishing for pirana - 3/22/2001"

	@param pguid Pointer to a database object's assigned GUID.
	@param pptss Address of a pointer to an ITsString COM object used for returning the text
					string.

	@return S_OK, E_POINTER, or E_FAIL.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP CleRecVc::GetStrForGuid(BSTR bstrGuid, ITsString ** pptss)
{
	Assert(false);  // rework

	BEGIN_COM_METHOD;
	ChkComBstrArg(bstrGuid);
	ChkComOutPtr(pptss);

	if (BstrLen(bstrGuid) != 8)
		ReturnHr(E_INVALIDARG);

	CleMainWnd * pcmw = dynamic_cast<CleMainWnd *>(AfApp::Papp()->GetCurMainWnd());
	AssertPtr(pcmw);
	CleLpInfo * plpi = dynamic_cast<CleLpInfo *>(pcmw->GetLpInfo());
	AssertPtr(plpi);

	HVO hvo = plpi->GetDbInfo()->GetIdFromGuid((GUID *)bstrGuid);

	CustViewDaPtr qcvd;
	plpi->GetDataAccess(&qcvd);
	AssertPtr(qcvd);
	int clid;
	HVO hvoOwn;
	int64 ntim;
	ITsStringPtr qtssTitle;
	CheckHr(qcvd->get_IntProp(hvo, kflidCmObject_Class, &clid));
	CheckHr(qcvd->get_ObjectProp(hvo, kflidCmObject_Owner, &hvoOwn));
			// REVIEW KenZ(RandyR) Whey are DN flids in this app?
	CheckHr(qcvd->get_TimeProp(hvo, kflidRnGenericRec_DateCreated, &ntim));
	CheckHr(qcvd->get_StringProp(hvo, kflidRnGenericRec_Title, &qtssTitle));

	int stid;
			// REVIEW KenZ(RandyR) Whey are DN flids in this app?
	if (clid == kclidRnEvent)
	{
		if (pcmw->GetRootObj() == hvoOwn)
			stid = kstidEvent;
		else
			stid = kstidSubevent;
	}
	else if (clid == kclidRnAnalysis)
	{
		if (pcmw->GetRootObj() == hvoOwn)
			stid = kstidAnalysis;
		else
			stid = kstidSubanalysis;
	}
	StrUni stu(stid);
	StrUni stuSep(kstidSpHyphenSp);

	ITsStrFactoryPtr qtsf;
	ITsIncStrBldrPtr qtisb;
	qtsf.CreateInstance(CLSID_TsStrFactory);
	CheckHr(qtsf->GetIncBldr(&qtisb));
	CheckHr(qtisb->Append(stu.Bstr()));

	CheckHr(qtisb->Append(stuSep.Bstr()));
	CheckHr(qtisb->AppendTsString(qtssTitle)); // The title.
	CheckHr(qtisb->Append(stuSep.Bstr()));
	// Leave the date blank if a date doesn't exist.
	if (ntim)
	{
		// Convert the date to a system date.
		SilTime tim = ntim;
		SYSTEMTIME stim;
		stim.wYear = (unsigned short) tim.Year();
		stim.wMonth = (unsigned short) tim.Month();
		stim.wDay = (unsigned short) tim.Date();

		// Then format it to a time based on the current user locale.
		achar rgchDate[50]; // Tuesday, August 15, 2000		mardi 15 août 2000
		::GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stim, NULL, rgchDate, 50);
		stu = rgchDate;
		CheckHr(qtisb->Append(stu.Bstr()));
	}
	CheckHr(qtisb->GetString(pptss));

	return S_OK;

	END_COM_METHOD(g_fact2, IID_IVwViewConstructor)
}
Exemple #3
0
/*----------------------------------------------------------------------------------------------
	Something has changed in the possibility list.
----------------------------------------------------------------------------------------------*/
void RnDeFeRoleParts::ListChanged(int nAction, HVO hvoPssl, HVO hvoSrc, HVO hvoDst, int ipssSrc,
	int ipssDst)
{
	if (hvoPssl != m_psslRole)
	{
		// Process changes for people lists.
		SuperClass::ListChanged(nAction, hvoPssl, hvoSrc, hvoDst, ipssSrc, ipssDst);
		return;
	}

	// If someone deleted the role we are interested in we need to clean up.
	if (hvoSrc == m_pssRole && nAction == kplnaDelete)
	{
		// Remove the notifier for the role list.
		Assert(m_psslRole);
		PossListInfoPtr qpli;
		GetLpInfo()->LoadPossList(m_psslRole, m_wsMagic, &qpli);
		AssertPtr(qpli);
		qpli->RemoveNotify(this);
		m_psslRole = 0;
		m_pssRole = 0;
	}
	// At this point we are not getting kplnaMerged at all since we are just deleting all
	// fields and recreating new ones. But at some point down the road we may want to switch
	// to where we don't delete and recreate. This would be the right action to take then.
	if (hvoSrc == m_pssRole && nAction == kplnaMerged)
	{
		// Switch to the new role.
		m_pssRole = hvoDst;
	}
	// Now reset the label in case we changed.
	// Use Participants for the unspecified editor label.
	ITsStringPtr qtssName;
	int wsUser = GetLpInfo()->GetDbInfo()->UserWs();
	AfUtil::GetResourceTss(kstidTlsOptParticipants, wsUser, &qtssName);
	ITsStringPtr qtssHelp = m_qfsp->m_qtssHelp;
	ITsStrFactoryPtr qtsf;
	qtsf.CreateInstance(CLSID_TsStrFactory);
	if (m_pssRole)
	{
		PossItemInfo * ppii;
		GetLpInfo()->GetPossListAndItem(m_pssRole, wsUser, &ppii, NULL);
		StrUni stuName;  // the Role's name
		ppii->GetName(stuName, m_pnt);
		qtsf->MakeStringRgch(stuName.Chars(), stuName.Length(), wsUser, &qtssName);

		ITsIncStrBldrPtr qtisb;
		qtisb.CreateInstance(CLSID_TsIncStrBldr);

		// Add the first substring.
		qtisb->AppendTsString(m_qfsp->m_qtssHelp);

		// Add the second substring.
		StrUni stuTemp;
		stuTemp.Load(kstidRnRoledPartic_HelpA);
		qtisb->AppendRgch(stuTemp.Chars(), stuTemp.Length());

		// Turn bold on.
		qtisb->SetIntPropValues(ktptBold, ktpvEnum, kttvForceOn);
		// Add the Role's name
		qtisb->AppendRgch(stuName.Chars(), stuName.Length());
		// Turn bold off.
		qtisb->SetIntPropValues(ktptBold, ktpvEnum, kttvOff);

		// Add the third substring.
		stuTemp.Load(kstidRnRoledPartic_HelpB);
		qtisb->AppendRgch(stuTemp.Chars(), stuTemp.Length());

		// Get the completed TsString.
		qtisb->GetString(&qtssHelp);
	}
	m_qtssLabel = qtssName;
	m_qtssHelp = qtssHelp;

	// Force the label to redraw.
	Rect rcLabel;
	::GetClientRect(m_qadsc->Hwnd(),&rcLabel);
	Rect rcEdit(m_rcClip);
	if (m_hwnd)
	{
		// We have an open edit box, so get the correct coordinates for the client window.
		::GetClientRect(m_hwnd, &rcEdit);
		::MapWindowPoints(m_hwnd, m_qadsc->Hwnd(), (POINT *)&rcEdit, 2);
	}
	rcLabel.top = rcEdit.top;
	rcLabel.bottom = rcEdit.bottom;
	rcLabel.right = m_qadsc->GetTreeWidth();
	::InvalidateRect(m_qadsc->Hwnd(), &rcLabel, false);
}