/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ // TabList.cpp : implementation file // #include "stdafx.h" #include "tclist.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CTCList // initialize string to calculate average char width CString CTCList::m_strCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; CTCList::CTCList() { m_nSpacing = 2; // init column spacing m_nTabs = MIN_TAB_SIZE; // init number of tabs m_nAvgCharWidth = 8; // a reasonable default // init size of tab setting and column width arrays m_aTabs.SetSize (MIN_TAB_SIZE); m_aColWidth.SetSize (MIN_TAB_SIZE); InitColWidth(); // init column width array } CTCList::~CTCList() { } BEGIN_MESSAGE_MAP(CTCList, CListBox) //{{AFX_MSG_MAP(CTCList) ON_MESSAGE(LB_ADDSTRING, OnAddString) ON_MESSAGE(LB_INSERTSTRING, OnInsertString) ON_MESSAGE(LB_DELETESTRING, OnDeleteString) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTCList message handlers // Set the number of spaces to separate columns. void CTCList::SetColumnSpace(int nSpacing) { // only process if different if (nSpacing != m_nSpacing) { m_nSpacing = nSpacing; // store the number of character spaces CalculateTabs(); // calculate new tab settings SetTabStops(m_nTabs, (LPINT) &m_aTabs[0]); // set tab settings } } // Calculate average character width. The average character width is // calculated using the same method used by GetDialogBaseUnits function; // average char width = (pixel width of "ABC...Zabc...z") / 52. // The current font is used for the calculation. void CTCList::CalculateAvgCharWidth(CDC* pDC) { CFont* pCurrentFont = GetFont(); // get font currently using for list box // GetFont will return NULL if using System font. // If using system font just call GetDialogBaseUnits. if (!pCurrentFont) m_nAvgCharWidth = LOWORD(GetDialogBaseUnits()); // if not using system font, select font into dc and // calculate average char width else { // have to select object into the dc before // we can calculate width of string CFont* pOldFont = pDC->SelectObject(pCurrentFont); // get width of string CSize size = pDC->GetTextExtent(m_strCharSet, m_strCharSet.GetLength()); // calculate average char width and round result m_nAvgCharWidth = MulDiv(1, size.cx, m_strCharSet.GetLength()); // select old font back into dc pDC->SelectObject(pOldFont); } } // calculate tabs from maximum column array void CTCList::CalculateTabs() { UINT nIndex; // index to array // first tab setting is the fist col width m_aTabs[0] = ((m_aColWidth[0]+(m_nAvgCharWidth*m_nSpacing)) * 4) / m_nAvgCharWidth; // calculate each tab setting for (nIndex=1; nIndex < m_nTabs; nIndex++) m_aTabs[nIndex] = m_aTabs[nIndex-1] + ((m_aColWidth[nIndex]+(m_nAvgCharWidth*m_nSpacing)) * 4) / m_nAvgCharWidth; } // re-calculate maximum column widths void CTCList::Recalc() { // we are totally recalculating, so reset size of arrays m_aTabs.SetSize(MIN_TAB_SIZE); // reset tab stop array size m_aColWidth.SetSize(MIN_TAB_SIZE); // reset col width array size m_nTabs = MIN_TAB_SIZE; // set number of tab settings InitColWidth(); // init col width array // loop through list box and calculate col widths for each string CString str; for (int nItem = GetCount() - 1; nItem >= 0; --nItem) { GetText(nItem, str); // get list box item string CalculateColWidths(str); // calculate column widths of string } CalculateTabs(); // calculate tab settings } // initialize column width to 0 void CTCList::InitColWidth() { // initialize col width settings to a length of 0 UINT nIndex; for (nIndex=0; nIndex < m_nTabs; nIndex++) m_aColWidth[nIndex] = 0; } // calculate column widths of string BOOL CTCList::CalculateColWidths(LPCSTR pString, BOOL bSetWidths) { BOOL bMaxColumn = FALSE; // returns if this string contains max column CDC* pDC = GetDC(); // get dc of list box window UINT nCol=0; // column currently processing if (pDC) { // calculate average char width CalculateAvgCharWidth(pDC); // select current font into dc so can measure width of string CFont* pOldFont = pDC->SelectObject(GetFont()); CString strRow; // row string CString strCol; // column string CSize size; // size of column string int nIndex=0; // index to row string strRow = pString; // set row string to passed string // divide row string up into column strings while (nIndex != -1) { // check if need to grow tab setting and column width if (nCol+1 > m_nTabs) { m_aTabs.SetSize(m_nTabs+1); m_aColWidth.SetSize(m_nTabs+1); m_nTabs += 1; } // parse out column string from row string if ((nIndex = strRow.Find('\t')) == -1) strCol = strRow; else { strCol = strRow.Left(nIndex); strRow = strRow.Mid(nIndex+1); } // get pixel width of column string size = pDC->GetTextExtent(strCol, strCol.GetLength()); // see if this is the widest column string if ((UINT)size.cx >= m_aColWidth[nCol]) { // this string contains a longest column string bMaxColumn = TRUE; // store information to column width array if (bSetWidths) m_aColWidth[nCol] = size.cx; } nCol++; // move to the next column } pDC->SelectObject(pOldFont); ReleaseDC(pDC); } return bMaxColumn; } // process the LB_INSERTSTRING message LRESULT CTCList::OnInsertString(WPARAM wParam, LPARAM lParam) { // adjust the col width array for this string BOOL bRet = CalculateColWidths((LPCSTR)lParam); // set tab stop if required if (bRet) { CalculateTabs(); // adjust the tab setting array SetTabStops(m_nTabs, (LPINT)&m_aTabs[0]); // set tab stops } return Default(); } // process the LB_ADDSTRING message LRESULT CTCList::OnAddString(WPARAM wParam, LPARAM lParam) { // adjust the col width array for this string BOOL bRet = CalculateColWidths((LPCSTR)lParam); // set tab stop if required if (bRet) { CalculateTabs(); // adjust the tab setting array SetTabStops(m_nTabs, (LPINT)&m_aTabs[0]); // set tab stops } return Default(); } // process the LB_DELETESTRING message LRESULT CTCList::OnDeleteString(WPARAM wParam, LPARAM lParam) { CString str; GetText(wParam, str); // see if need to recalculate tab stops BOOL bRecalc = CalculateColWidths(str, FALSE); // delete string from list box // pass message along to list box proc LRESULT lRet = Default(); // recalculate tab stops if required if (bRecalc) { Recalc(); SetTabStops(m_nTabs, (LPINT)&m_aTabs[0]); } return lRet; }