1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
31 // Contact(s): julians
33 // Version: $Id: mltwin.cpp,v 1.2 2001/03/22 11:27:28 julians Exp $
35 // Description: Implementation file for ecMemoryLayoutWindow
42 //####DESCRIPTIONEND####
44 //===========================================================================
46 // ============================================================================
48 // ============================================================================
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 #pragma implementation "mltwin.h"
57 // Includes other headers for precompiled compilation
65 #include "sectiondlg.h"
67 #define VERT_BORDER 30 /* the vertical border at the top/bottom of the client area */
68 #define HORIZ_BORDER 30 /* the horizontal border at the left/right of the client area */
69 #define BAR_HEIGHT 18 /* the height of the memory section caption bar */
70 #define MAP_HEIGHT 66 /* the height of each memory section rectangle (including caption bar) */
71 #define REGION_SPACING 115 /* the vertical offset between successive memory regions */
72 #define ADDRESS_TEXT_SPACE 0.9 /* use 90% of the section width to draw the address */
73 #define EXTERNAL_TEXT_BORDER 5 /* spacing between external text and border of region */
74 #define ADDRESS_FORMAT _T("%08X") /* draw memory addresses in hex format */
75 #define UNITS_PER_SECTION 3 /* memory section width in units, unused sections are 1 unit wide */
76 #define UNIT_WIDTH_MIN 27 /* minimum width of memory section unit before horizontal scrolling enabled */
77 #define TICK_HEIGHT 4 /* the height of the tick marks on the memory sections and regions */
79 #define DISPLAY_MODE 1 /* 1 == const unit width for all regions */
80 /* 2 == const region width for all regions */
84 * ecMemoryLayoutWindow
87 IMPLEMENT_CLASS(ecMemoryLayoutWindow, wxScrolledWindow)
89 BEGIN_EVENT_TABLE(ecMemoryLayoutWindow, wxScrolledWindow)
90 // EVT_PAINT(ecMemoryLayoutWindow::OnPaint)
91 EVT_MOUSE_EVENTS(ecMemoryLayoutWindow::OnMouseEvent)
92 EVT_PAINT(ecMemoryLayoutWindow::OnPaint)
93 EVT_SIZE(ecMemoryLayoutWindow::OnSize)
94 EVT_MENU(ecID_TREE_PROPERTIES, ecMemoryLayoutWindow::OnProperties)
97 ecMemoryLayoutWindow::ecMemoryLayoutWindow(wxWindow* parent, wxWindowID id, const wxPoint& pt,
98 const wxSize& sz, long style):
99 wxScrolledWindow(parent, id, pt, sz, style)
105 SetBackgroundColour(* wxWHITE);
107 m_propertiesMenu = new wxMenu;
109 m_propertiesMenu->Append(ecID_WHATS_THIS, _("&What's This?"));
110 m_propertiesMenu->AppendSeparator();
111 m_propertiesMenu->Append(ecID_TREE_PROPERTIES, _("P&roperties"));
114 ecMemoryLayoutWindow::~ecMemoryLayoutWindow()
116 delete m_propertiesMenu;
119 void ecMemoryLayoutWindow::OnPaint(wxPaintEvent& event)
125 ecConfigToolDoc* pDoc = wxGetApp().GetConfigToolDoc();
126 if (pDoc == NULL) // no document so nothing to draw
130 // clear the lists of region and section rectangles used for hit testing
132 listRegionRect.RemoveAll ();
133 listSectionRect.RemoveAll ();
135 // setup background mode
137 int nOldBkMode = pDC->SetBkMode (TRANSPARENT);
142 if (!fntName.CreatePointFont (80, _T("MS Sans Serif"), pDC))
144 CFont * pOldFont = pDC->SelectObject (&fntName);
146 // determine max unit count for any region
148 mem_map * pMemoryMap = &CConfigTool::GetConfigToolDoc()->MemoryMap;
150 // calculate the unit scaling for DISPLAY_MODE 1
152 UINT uPixelsPerUnit = UNIT_WIDTH_MIN;
154 if (m_uUnitCountMax != 0) // if there is something to draw
157 GetClientRect (&rectClientRect);
158 uPixelsPerUnit = __max ((m_uClientWidth - HORIZ_BORDER * 2) / m_uUnitCountMax, UNIT_WIDTH_MIN);
159 m_uViewWidth = uPixelsPerUnit * m_uUnitCountMax + HORIZ_BORDER * 2;
166 list <mem_region>::iterator region;
167 for (region = pMemoryMap->region_list.begin (); region != pMemoryMap->region_list.end (); ++region)
170 for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
171 uUnitCount += (section_view->section == NULL ? 1 : UNITS_PER_SECTION);
173 if (DISPLAY_MODE == 1)
174 DrawRegion (pDC, uRegion++, uUnitCount, uPixelsPerUnit, region);
175 else // DISPLAY_MODE == 2
176 DrawRegion (pDC, uRegion++, uUnitCount, (rectClientRect.right - HORIZ_BORDER * 2) / uUnitCount, region);
179 pDC->SelectObject (pOldFont);
180 pDC->SetBkMode (nOldBkMode);
184 void ecMemoryLayoutWindow::OnMouseEvent(wxMouseEvent& event)
186 if (event.RightDown())
188 PopupMenu(GetPropertiesMenu(), event.GetX(), event.GetY());
192 void ecMemoryLayoutWindow::OnProperties(wxCommandEvent& event)
194 ecSectionDialog dialog(wxTheApp->GetTopWindow());
198 void ecMemoryLayoutWindow::RefreshMLT()
201 // From OnUpdate in the MFC tool
203 if ((lHint != 0) && (pHint != NULL) && (lHint != CConfigToolDoc::MemLayoutChanged))
204 return; // no need to invalidate the view
205 m_arstrTooltipRects.RemoveAll();
207 CalcUnitCountMax (); // recalculate the total view width since the section count may have changed
208 if (m_uUnitCountMax == 0 || (m_uClientWidth < HORIZ_BORDER * 2)) // there is nothing to draw
210 else // allow horizontal scrolling when the unit width reduces to UNIT_WIDTH_MIN
211 m_uViewWidth = __max ((m_uClientWidth - HORIZ_BORDER * 2) / m_uUnitCountMax, UNIT_WIDTH_MIN) * m_uUnitCountMax + HORIZ_BORDER * 2;
214 sizeTotal.cx = __max (m_uViewWidth, m_uClientWidth);
215 sizeTotal.cy = CConfigTool::GetConfigToolDoc()->MemoryMap.region_list.size () * REGION_SPACING + EXTERNAL_TEXT_BORDER * 2;
216 SetScrollSizes (MM_TEXT, sizeTotal);
221 void ecMemoryLayoutWindow::DrawRegion (wxDC& dc, int uRegion, int uUnitCount, int uPixelsPerUnit, std::list <mem_region>::iterator region)
224 BOOL bDrawFocusRect = FALSE;
228 // setup the drawing objects
230 CBrush brshUnusedSection;
231 if (!brshUnusedSection.CreateHatchBrush (HS_BDIAGONAL, RGB (128, 128, 128)))
234 CBrush brshUsedSection;
235 if (!brshUsedSection.CreateSolidBrush (GetSysColor (COLOR_WINDOW)))
238 CBrush brshInitialSectionBar;
239 if (!brshInitialSectionBar.CreateSolidBrush (GetSysColor (COLOR_INACTIVECAPTION)))
242 CBrush brshFixedSectionBar;
243 if (!brshFixedSectionBar.CreateSolidBrush (GetSysColor (COLOR_ACTIVECAPTION)))
246 CBrush brshFinalSectionBar;
247 if (!brshFinalSectionBar.CreateSolidBrush (GetSysColor (COLOR_ACTIVECAPTION)))
251 if (!penBorder.CreatePen (PS_SOLID, 1, GetSysColor (COLOR_WINDOWTEXT)))
255 if (!penSelected.CreatePen (PS_SOLID, 2, GetSysColor (COLOR_WINDOWTEXT)))
258 // select the border pen object
260 CPen * pOldPen = pDC->SelectObject (&penBorder);
262 // calculate the region rectangle
265 srRegion.Rect.SetRect (HORIZ_BORDER, VERT_BORDER + REGION_SPACING * uRegion, HORIZ_BORDER + uUnitCount * uPixelsPerUnit + 1, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + 1);
266 srRegion.Region = region;
267 listRegionRect.AddTail (srRegion);
271 CPoint pointOrigin (srRegion.Rect.left, srRegion.Rect.top);
272 pDC->LPtoDP (&pointOrigin);
275 pDC->SetBrushOrg (pointOrigin);
276 CBrush * pOldBrush = pDC->SelectObject (&brshUnusedSection);
277 pDC->Rectangle (srRegion.Rect);
279 pDC->MoveTo (srRegion.Rect.left, srRegion.Rect.bottom - 1); // draw tick
280 pDC->LineTo (srRegion.Rect.left, srRegion.Rect.bottom + TICK_HEIGHT); // draw tick
282 if (region == m_riSelectedRegion)
284 bDrawFocusRect = TRUE;
285 m_rectSelectedItem = srRegion.Rect;
288 // draw the region label
290 CRect rectRegionLabel (HORIZ_BORDER, VERT_BORDER + REGION_SPACING * uRegion - EXTERNAL_TEXT_BORDER - 20, m_uViewWidth - HORIZ_BORDER /*HORIZ_BORDER + uUnitCount * uPixelsPerUnit + 1*/, VERT_BORDER + REGION_SPACING * uRegion - EXTERNAL_TEXT_BORDER);
291 CString strRegionLabel;
292 strRegionLabel.Format (_T("%s (%08X-%08X)%s"), CString(region->name.c_str ()), region->address, region->address + region->size - 1, ((region->type == read_only) ? _T(" read only") : _T("")));
293 pDC->DrawText (strRegionLabel, -1, rectRegionLabel, DT_BOTTOM | DT_SINGLELINE);
295 // draw the start address of the region
297 rectAddress.SetRect (HORIZ_BORDER, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, HORIZ_BORDER + ADDRESS_TEXT_SPACE * UNITS_PER_SECTION * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
298 strAddress.Format (ADDRESS_FORMAT, region->address);
299 pDC->DrawText (strAddress, -1, rectAddress, DT_LEFT | DT_SINGLELINE);
301 // draw the end address of the region
303 rectAddress.SetRect (HORIZ_BORDER + (uUnitCount - ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, HORIZ_BORDER + (uUnitCount + ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
304 strAddress.Format (ADDRESS_FORMAT, region->address + region->size);
305 pDC->DrawText (strAddress, -1, rectAddress, DT_CENTER | DT_SINGLELINE);
307 // draw the sections within the region
309 UINT uSectionUnitCount = 0;
311 SECTIONRECT srSection;
312 for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
314 if (section_view->section != NULL) // the section is used
318 pDC->SelectObject (brshUsedSection);
319 srSection.Rect.SetRect (HORIZ_BORDER + uSectionUnitCount * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion, HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION) * uPixelsPerUnit + 1, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + 1);
320 srSection.SectionView = section_view;
321 listSectionRect.AddTail (srSection);
322 pDC->Rectangle (srSection.Rect);
323 if (section_view == m_sviSelectedSectionView)
325 bDrawFocusRect = TRUE;
326 m_rectSelectedItem = srSection.Rect;
329 // draw text within the section
331 CString strSection, strSectionLine;
333 if ((section_view->section_location != initial_location) && (section_view->section->alignment > 1))
335 strSectionLine.Format (_T("align %lX\n"), section_view->section->alignment);
336 strSection += strSectionLine;
339 if (section_view->section->size > 0)
341 strSectionLine.Format (_T("size %lX\n"), section_view->section->size);
342 strSection += strSectionLine;
345 if (section_view->section_location == final_location)
347 strSectionLine.Format (_T("relocated\n"));
348 strSection += strSectionLine;
351 pDC->DrawText (strSection, -1, srSection.Rect - (LPCRECT) CRect (EXTERNAL_TEXT_BORDER, EXTERNAL_TEXT_BORDER + BAR_HEIGHT, EXTERNAL_TEXT_BORDER, EXTERNAL_TEXT_BORDER), DT_LEFT);
353 // select caption bar colour according to type of section
355 if (section_view->section_location == initial_location)
357 pDC->SetTextColor (GetSysColor (COLOR_INACTIVECAPTIONTEXT));
358 pDC->SelectObject (&brshInitialSectionBar);
362 pDC->SetTextColor (GetSysColor (COLOR_CAPTIONTEXT));
363 pDC->SelectObject (&brshFinalSectionBar);
366 // draw the caption bar
368 rectBar.SetRect (HORIZ_BORDER + uSectionUnitCount * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion, HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION) * uPixelsPerUnit + 1, VERT_BORDER + REGION_SPACING * uRegion + BAR_HEIGHT + 1);
369 pDC->Rectangle (rectBar);
371 // draw the section name within the caption bar
373 CString strName(section_view->section->name.c_str ());
375 m_arstrTooltipRects.Lookup(strName,(void *&)pRect);
377 if(pDC->GetTextExtent(strName).cx>rectBar.Width()-2*EXTERNAL_TEXT_BORDER){
380 pRect->CopyRect(rectBar);
383 m_arstrTooltipRects.SetAt(strName,pRect);
385 // Replace final three characters of name with an elipsis
386 int nLength=1+max(1,strName.GetLength()-3);
389 strName=strName.Left(nLength)+_T("...");
390 } while(nLength>1 && pDC->GetTextExtent(strName).cx>rectBar.Width()-2*EXTERNAL_TEXT_BORDER);
392 rectBar.left+=EXTERNAL_TEXT_BORDER;
393 rectBar.right-=EXTERNAL_TEXT_BORDER;
397 m_arstrTooltipRects.RemoveKey(strName);
401 pDC->DrawText (strName, -1, rectBar, format | DT_VCENTER | DT_SINGLELINE);
402 pDC->SetTextColor (GetSysColor (COLOR_WINDOWTEXT));
404 // find the mem_section item describing the current section_view item
406 list <mem_section>::iterator MemorySection = section_view->section;
408 // draw the section address if appropriate
410 if ((section_view->section_location == initial_location))
412 if (MemorySection->initial_location->anchor == absolute)
414 pDC->MoveTo (srSection.Rect.left, srSection.Rect.bottom - 1); // draw tick
415 pDC->LineTo (srSection.Rect.left, srSection.Rect.bottom + TICK_HEIGHT); // draw tick
416 rectAddress.SetRect (HORIZ_BORDER + uSectionUnitCount * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, (int) (HORIZ_BORDER + (uSectionUnitCount + ADDRESS_TEXT_SPACE * UNITS_PER_SECTION) * uPixelsPerUnit), VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
417 strAddress.Format (ADDRESS_FORMAT, MemorySection->initial_location->address);
418 pDC->DrawText (strAddress, -1, rectAddress, DT_LEFT | DT_SINGLELINE);
421 if (MemorySection->size > 0) // the end address can be calculated
423 rectAddress.SetRect (HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION - ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION + ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
424 strAddress.Format (ADDRESS_FORMAT, MemorySection->initial_location->address + MemorySection->size);
425 pDC->DrawText (strAddress, -1, rectAddress, DT_CENTER | DT_SINGLELINE);
431 else if ((section_view->section_location == final_location) || (section_view->section_location == fixed_location))
433 if (MemorySection->final_location->anchor == absolute)
435 pDC->MoveTo (srSection.Rect.left, srSection.Rect.bottom - 1); // draw tick
436 pDC->LineTo (srSection.Rect.left, srSection.Rect.bottom + TICK_HEIGHT); // draw tick
437 rectAddress.SetRect (HORIZ_BORDER + uSectionUnitCount * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, (int) (HORIZ_BORDER + (uSectionUnitCount + ADDRESS_TEXT_SPACE * UNITS_PER_SECTION) * uPixelsPerUnit), VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
438 strAddress.Format (ADDRESS_FORMAT, MemorySection->final_location->address);
439 pDC->DrawText (strAddress, -1, rectAddress, DT_LEFT | DT_SINGLELINE);
442 if (MemorySection->size > 0) // the end address can be calculated
444 rectAddress.SetRect (HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION - ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER, HORIZ_BORDER + (uSectionUnitCount + UNITS_PER_SECTION + ADDRESS_TEXT_SPACE) * uPixelsPerUnit, VERT_BORDER + REGION_SPACING * uRegion + MAP_HEIGHT + EXTERNAL_TEXT_BORDER + 30);
445 strAddress.Format (ADDRESS_FORMAT, MemorySection->final_location->address + MemorySection->size);
446 pDC->DrawText (strAddress, -1, rectAddress, DT_CENTER | DT_SINGLELINE);
452 uSectionUnitCount += UNITS_PER_SECTION;
456 uSectionUnitCount++; // unused sections occupy a single unit
460 // draw the focus rectangle around the selected object (if any)
463 pDC->DrawFocusRect (m_rectSelectedItem + CRect (1, 1, 1, 1));
465 // restore previous drawing objects
467 pDC->SelectObject (pOldBrush);
468 pDC->SelectObject (pOldPen);
472 SECTIONRECT * ecMemoryLayoutWindow::SectionHitTest (wxPoint pntTest)
475 for (POSITION posSection = listSectionRect.GetHeadPosition (); posSection != NULL; listSectionRect.GetNext (posSection))
477 if (listSectionRect.GetAt (posSection).Rect.PtInRect (pntTest))
478 return & listSectionRect.GetAt (posSection);
485 REGIONRECT * ecMemoryLayoutWindow::RegionHitTest (wxPoint pntTest)
488 for (POSITION posRegion = listRegionRect.GetHeadPosition (); posRegion != NULL; listRegionRect.GetNext (posRegion))
490 CRect rectRegion = listRegionRect.GetAt (posRegion).Rect +
491 CRect (EXTERNAL_TEXT_BORDER + 20, EXTERNAL_TEXT_BORDER + 20, EXTERNAL_TEXT_BORDER + 20, EXTERNAL_TEXT_BORDER + 20); // extended rectangle to allow clicking on region label
492 if (rectRegion.PtInRect (pntTest))
493 return & listRegionRect.GetAt (posRegion);
501 void ecMemoryLayoutWindow::OnSize(wxSizeEvent& event)
504 CScrollView::OnSize(nType, cx, cy);
507 if (m_uUnitCountMax == 0) // there is nothing to draw
509 else // allow horizontal scrolling when the unit width reduces to UNIT_WIDTH_MIN
510 m_uViewWidth = __max ((cx - HORIZ_BORDER * 2) / m_uUnitCountMax, UNIT_WIDTH_MIN) * m_uUnitCountMax + HORIZ_BORDER * 2;
513 sizeTotal.cx = __max (m_uViewWidth, m_uClientWidth);
514 if (CConfigTool::GetConfigToolDoc() == NULL)
517 sizeTotal.cy = CConfigTool::GetConfigToolDoc()->MemoryMap.region_list.size () * REGION_SPACING + EXTERNAL_TEXT_BORDER * 2;
518 SetScrollSizes (MM_TEXT, sizeTotal);
522 void ecMemoryLayoutWindow::CalcUnitCountMax ()
525 UINT uUnitCountMax = 0;
527 list <mem_region>::iterator region;
528 mem_map * pMemoryMap = & (CConfigTool::GetConfigToolDoc()->MemoryMap);
529 for (region = pMemoryMap->region_list.begin (); region != pMemoryMap->region_list.end (); ++region)
532 for (list <mem_section_view>::iterator section_view = region->section_view_list.begin (); section_view != region->section_view_list.end (); ++section_view)
533 uUnitCount += (section_view->section == NULL ? 1 : UNITS_PER_SECTION);
535 if (uUnitCount > uUnitCountMax)
536 uUnitCountMax = uUnitCount;
538 m_uUnitCountMax = uUnitCountMax;