Index: /trunk/images/dialogs/changesetdialog.svg
===================================================================
--- /trunk/images/dialogs/changesetdialog.svg	(revision 2613)
+++ /trunk/images/dialogs/changesetdialog.svg	(revision 2613)
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="24"
+   height="24"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   version="1.0"
+   sodipodi:docname="changesetdialog.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-filename="C:\data\projekte\eclipse-3.5-ws\JOSM\images\dialogs\changesetdialog.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient1400">
+      <stop
+         id="stop1401"
+         offset="0.0000000"
+         style="stop-color:#000000;stop-opacity:0.67843139;" />
+      <stop
+         id="stop1403"
+         offset="0.56999999"
+         style="stop-color:#000000;stop-opacity:0.32941177;" />
+      <stop
+         id="stop1402"
+         offset="1.0000000"
+         style="stop-color:#000000;stop-opacity:0.00000000;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1400"
+       id="linearGradient17450"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.1148815,0,0,0.111489,-49.944348,-46.709945)"
+       x1="537.42401"
+       y1="580.16663"
+       x2="539.39642"
+       y2="510.39194" />
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="6.1230318e-14 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+    <inkscape:perspective
+       id="perspective3269"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective4004"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective4054"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <inkscape:perspective
+       id="perspective4104"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       sodipodi:type="inkscape:persp3d" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="15.839192"
+     inkscape:cx="10.413603"
+     inkscape:cy="4.1433882"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1025"
+     inkscape:window-height="824"
+     inkscape:window-x="228"
+     inkscape:window-y="77" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Ebene 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       sodipodi:type="inkscape:offset"
+       inkscape:radius="4.5834389"
+       inkscape:original="M 547.25 494.90625 C 547.15581 494.91224 547.06196 494.92267 546.96875 494.9375 C 546.73282 494.97719 546.68628 494.99521 546.84375 494.96875 C 524.84282 498.66333 486.64226 504.70723 464.125 512.78125 C 463.15567 513.13537 462.43455 513.95957 462.21875 514.96875 C 462.15787 515.25343 462.16594 515.52974 462.1875 515.8125 C 462.05699 516.6851 462.30033 517.57519 462.90625 518.25 C 470.3466 526.58465 475.04831 536.96666 477.65625 546.5625 C 480.26419 556.15834 480.71815 565.04611 480 569.8125 C 479.30782 574.40653 476.22839 582.0513 474.59375 588.9375 C 473.77643 592.3806 473.25435 595.69511 473.90625 598.84375 C 474.55815 601.99239 477.07104 604.95638 480.71875 605.78125 C 480.7809 605.79364 480.84344 605.80407 480.90625 605.8125 C 502.83748 609.49724 508.3071 611.152 530.28125 619.03125 C 531.00412 619.2851 531.77801 619.24067 532.46875 618.9375 C 532.87181 618.81636 533.26667 618.66906 533.71875 618.53125 C 555.08828 610.94998 576.58139 605.04634 597.875 601.46875 C 597.95919 601.45151 598.0426 601.43065 598.125 601.40625 C 601.50992 600.51027 603.68441 597.45149 604.21875 594.40625 C 604.75309 591.36101 604.30268 588.11024 603.59375 584.6875 C 602.17588 577.84201 599.46382 570.20636 598.75 565.46875 C 598.03185 560.70236 598.51706 551.81459 601.125 542.21875 C 603.73294 532.62291 608.43467 522.24088 615.875 513.90625 C 616.46759 513.24343 616.73797 512.38142 616.625 511.53125 C 616.62371 511.52157 616.62638 511.50967 616.625 511.5 C 616.65564 511.14932 616.62753 510.78679 616.53125 510.4375 C 616.25916 509.45037 615.50959 508.67713 614.53125 508.375 C 592.67011 501.65325 570.38545 497.83074 547.875 494.9375 C 547.66833 494.90533 547.45885 494.89485 547.25 494.90625 z "
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.00000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="path2509"
+       d="M 546.96875,490.34375 C 546.73069,490.35889 546.48536,490.3688 546.25,490.40625 C 546.23958,490.40621 546.22917,490.40621 546.21875,490.40625 C 546.18701,490.41159 546.10787,490.43747 546.09375,490.4375 C 546.08297,490.43753 546.00824,490.4694 546,490.46875 C 524.03634,494.156 485.91874,500.0939 462.5625,508.46875 C 460.12832,509.35802 458.2957,511.44805 457.75,514 C 457.64304,514.50016 457.69346,514.75022 457.6875,515.125 L 457.65625,515.125 C 457.64549,515.19696 457.66489,515.27144 457.65625,515.34375 C 457.65949,515.59267 457.61289,515.99741 457.625,516.15625 L 457.71875,516.15625 C 457.7004,517.9925 458.20677,519.87224 459.5,521.3125 C 466.31992,528.95215 470.75702,538.69215 473.21875,547.75 C 475.67414,556.78454 476.01944,565.47005 475.46875,569.125 C 474.96335,572.47938 471.88234,580.4719 470.125,587.875 C 469.25632,591.53448 468.52638,595.53153 469.40625,599.78125 C 470.41647,604.66054 474.20882,609.00402 479.71875,610.25 C 479.74989,610.26075 479.78114,610.27117 479.8125,610.28125 C 479.96915,610.31248 480.122,610.32238 480.28125,610.34375 C 502.11416,614.01197 506.78015,615.47725 528.71875,623.34375 C 528.72917,623.34379 528.73958,623.34379 528.75,623.34375 C 530.40543,623.92509 532.17716,623.80119 533.75,623.25 L 533.78125,623.3125 C 534.02995,623.23775 534.12934,623.18613 534.3125,623.125 C 534.56656,623.04021 534.89238,622.95811 535.0625,622.90625 C 535.12544,622.88677 535.18796,622.86593 535.25,622.84375 C 556.41348,615.33558 577.64691,609.52458 598.625,606 C 598.67726,605.99049 598.72935,605.98007 598.78125,605.96875 C 598.99443,605.9251 599.2296,605.87406 599.4375,605.8125 C 604.84753,604.38048 607.90888,599.80302 608.71875,595.1875 C 609.42483,591.16351 608.84138,587.35958 608.09375,583.75 C 606.57774,576.43069 603.84834,568.54503 603.28125,564.78125 C 602.73348,561.14567 603.10468,552.44974 605.5625,543.40625 C 608.02422,534.34841 612.46135,524.60837 619.28125,516.96875 C 620.51026,515.59409 621.05725,513.76559 621.0625,511.90625 L 621.1875,511.90625 C 621.20597,511.69481 621.124,511.46534 621.125,511.25 C 621.11555,511.14318 621.17044,511.04431 621.15625,510.9375 C 621.32932,512.23623 621.34875,512.19262 621.15625,510.84375 L 621.09375,510.84375 C 621.06785,510.30541 621.08958,509.77048 620.9375,509.21875 C 620.25532,506.74384 618.3293,504.75794 615.875,504 C 593.64408,497.16455 571.10612,493.3158 548.46875,490.40625 C 547.94647,490.32495 547.52805,490.31493 547,490.34375 C 546.98958,490.34371 546.97917,490.34371 546.96875,490.34375 z"
+       transform="matrix(0.1135532,0,0,0.111489,-49.335921,-46.595244)" />
+    <path
+       style="fill:#868686;fill-opacity:1;stroke:none;stroke-width:6.00000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 12.924605,8.4666578 C 12.913779,8.4673258 12.902997,8.4684873 12.89229,8.4701416 C 12.865186,8.4745657 12.859837,8.4765759 12.877931,8.4736259 C 12.786503,8.4888493 12.705252,8.5391968 12.652552,8.6132887 C 12.599857,8.6873791 12.580157,8.7789571 12.597907,8.8673206 C 13.063685,11.178246 12.549429,13.423784 12.411222,14.69262 C 12.368911,15.081069 12.239522,15.593805 12.127614,16.117589 C 12.015699,16.641374 11.918992,17.175433 11.97324,17.661015 C 11.987118,17.776601 12.061895,17.876879 12.170691,17.925802 L 12.170691,17.967609 C 12.208734,17.966363 12.256131,17.965642 12.314297,17.96064 L 12.314297,17.957156 C 12.326251,17.957763 12.338236,17.957763 12.350195,17.957156 C 13.408446,17.851867 14.413515,17.156796 15.706891,15.929452 C 17.00026,14.702105 18.596283,12.915142 20.808352,10.511782 C 20.887089,10.42697 20.915822,10.309046 20.884563,10.198996 C 20.853304,10.088942 20.766372,10.001956 20.653979,9.9682752 C 18.142536,9.2188742 15.58244,8.792705 12.996401,8.4701416 C 12.972662,8.4665551 12.948593,8.4653868 12.924605,8.4666578 z"
+       id="path2444" />
+    <path
+       style="fill:#868686;fill-opacity:1;stroke:none;stroke-width:6.00000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 12.89588,8.4701416 C 12.889866,8.4711476 12.883882,8.4723092 12.877931,8.4736259 C 10.350431,8.8855312 5.9618883,9.5593602 3.3750696,10.459523 C 3.2637103,10.499003 3.1810754,10.591254 3.1562839,10.703766 C 3.131498,10.816276 3.1680252,10.933259 3.2530097,11.013483 C 5.6953752,13.323085 7.3848559,15.082627 8.745786,16.260433 C 10.106717,17.438241 11.183197,18.073268 12.350195,17.957156 C 12.441799,17.948375 12.525979,17.904399 12.583977,17.835025 C 12.641968,17.765654 12.66896,17.676651 12.65894,17.587849 C 12.621333,17.251276 12.694381,16.759684 12.802537,16.253466 C 12.9107,15.74725 13.046291,15.227179 13.096921,14.7623 C 13.224499,13.591049 13.776479,11.21938 13.276427,8.7384122 C 13.241924,8.5658384 13.075658,8.448632 12.89588,8.4701416 z"
+       id="path2453" />
+    <path
+       style="fill:url(#linearGradient17450);fill-opacity:1;stroke:none;stroke-width:6.00000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 12.924605,8.4666578 C 12.914969,8.4672523 12.905428,8.4687664 12.89588,8.4701416 C 12.894703,8.4703113 12.893467,8.4699603 12.89229,8.4701416 C 12.865186,8.4745657 12.859837,8.4765759 12.877931,8.4736259 C 10.350431,8.8855312 5.9618883,9.5593602 3.3750696,10.459523 C 3.2637103,10.499003 3.1808704,10.590893 3.1560777,10.703404 C 3.1312858,10.815918 3.1680252,10.933259 3.2530097,11.013483 C 5.6953752,13.323085 7.3848559,15.082627 8.745786,16.260433 C 10.037021,17.377925 11.07132,18.005298 12.170691,17.967609 C 12.187819,17.96705 12.214268,17.964912 12.235314,17.964124 C 12.261459,17.962615 12.288066,17.962907 12.314297,17.96064 C 12.326256,17.959609 12.33821,17.95835 12.350195,17.957156 C 13.408446,17.851867 14.413515,17.156796 15.706891,15.929452 C 17.00026,14.702105 18.596283,12.915142 20.808352,10.511782 C 20.887089,10.42697 20.915001,10.308271 20.883741,10.198221 C 20.852484,10.088165 20.766372,10.001956 20.653979,9.9682752 C 18.142536,9.2188742 15.58244,8.792705 12.996401,8.4701416 C 12.985745,8.4685309 12.974844,8.4707738 12.964093,8.4701416 C 12.950893,8.4693629 12.937823,8.4659578 12.924605,8.4666578 z"
+       id="path2521" />
+    <image
+       y="0.1322051"
+       x="2.9311147"
+       id="image3271"
+       height="10.642858"
+       width="10.464286"
+       sodipodi:absref="C:\data\projekte\eclipse-3.5-ws\JOSM\images\data\node.png"
+       xlink:href="C:\data\projekte\eclipse-3.5-ws\JOSM\images\data\node.png" />
+    <image
+       y="5.1982875"
+       x="9.66008"
+       id="image4176"
+       height="12.25"
+       width="11.982143"
+       sodipodi:absref="C:\data\projekte\eclipse-3.5-ws\JOSM\images\data\node.png"
+       xlink:href="C:\data\projekte\eclipse-3.5-ws\JOSM\images\data\node.png" />
+    <image
+       y="5.3641677"
+       x="2.6339738"
+       id="image4172"
+       height="12.25"
+       width="11.982143"
+       sodipodi:absref="C:\data\projekte\eclipse-3.5-ws\JOSM\images\data\node.png"
+       xlink:href="C:\data\projekte\eclipse-3.5-ws\JOSM\images\data\node.png" />
+    <path
+       style="fill:#a5a5a5;fill-opacity:1;stroke:none;stroke-width:6.00000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 3.4720008,10.511782 C 3.3397013,10.519066 3.2234186,10.599308 3.1728865,10.718192 C 3.1223611,10.837074 3.1465234,10.973543 3.2350604,11.069226 C 4.0898189,11.998449 4.6299567,13.155928 4.929564,14.22576 C 5.2291652,15.295591 5.2813174,16.28648 5.1988132,16.81788 C 5.1192951,17.330065 4.7655289,18.18237 4.577736,18.950107 C 4.483846,19.333974 4.4238601,19.703506 4.4987542,20.054543 C 4.5736483,20.405583 4.8623293,20.736036 5.2813861,20.827999 C 5.2885284,20.82938 5.2957144,20.830542 5.3029246,20.831482 C 7.8224215,21.242291 8.4507791,21.426777 10.975205,22.305229 C 11.075864,22.339532 11.187223,22.326668 11.276769,22.270388 C 12.904219,21.248857 13.986669,20.640894 14.716034,20.099835 C 15.445405,19.558779 15.843565,19.021368 15.922294,18.298593 C 15.971357,17.848175 15.760389,17.402269 15.455586,16.904981 C 15.150784,16.407691 14.727881,15.86447 14.252921,15.30581 C 13.302995,14.188491 12.144834,13.010651 11.352162,12.117921 C 11.294712,12.052911 11.213767,12.011761 11.125989,12.002947 C 8.4177034,11.74705 6.0994113,11.399503 3.6084268,10.532686 C 3.5648694,10.516858 3.5184637,10.509748 3.4720008,10.511782 z"
+       id="path2442" />
+    <path
+       style="fill:#a5a5a5;fill-opacity:1;stroke:none;stroke-width:6.00000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 20.549866,10.027502 C 20.502912,10.027678 20.45649,10.037164 20.413446,10.055376 C 18.059083,11.053067 13.700468,11.846209 11.061368,11.999464 C 10.90453,12.009545 10.77458,12.121322 10.745444,12.271218 C 10.243386,14.754362 10.7937,17.126645 10.921358,18.298593 C 10.996794,18.991157 11.209678,19.832623 11.341392,20.507468 C 11.429257,20.957667 11.611714,22.312547 10.975205,22.305229 C 11.130072,22.345111 11.231615,22.290452 11.370111,22.249484 C 13.825078,21.404256 16.294237,20.746064 18.740483,20.347201 C 18.750156,20.345279 18.759737,20.342954 18.769205,20.340235 C 19.158069,20.240343 19.407877,19.899322 19.469263,19.559812 C 19.530648,19.220301 19.478906,18.857876 19.397461,18.476278 C 19.234574,17.713081 18.923009,16.861791 18.841003,16.333599 C 18.758502,15.802198 18.814244,14.81131 19.113848,13.741478 C 19.413453,12.67165 19.953595,11.514168 20.808352,10.584948 C 20.899121,10.486418 20.921679,10.346618 20.865792,10.22609 C 20.809907,10.105569 20.686056,10.026918 20.549866,10.027502 z"
+       id="path2440"
+       sodipodi:nodetypes="csccsscccsssssssc" />
+    <path
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:6.00000191;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 10.537223,12.022665 C 10.447196,14.256974 10.661346,16.197299 10.70595,17.326981 C 10.743661,18.281725 10.912576,19.442522 11.007513,20.372838 C 11.053826,20.826622 11.12298,21.948094 10.908157,22.514315 L 11.370111,22.466273 C 11.231615,22.521717 11.130072,22.595683 10.975205,22.541713 C 11.611714,22.551617 11.429257,20.718054 11.341392,20.108799 C 11.209678,19.195529 10.996794,18.05677 10.921358,17.119522 C 10.833595,16.029147 10.545219,14.169517 10.537223,12.022665 z"
+       id="path2495"
+       sodipodi:nodetypes="csssccssc" />
+    <image
+       y="1.4718096"
+       x="9.2844448"
+       id="image4178"
+       height="10.642858"
+       width="10.464286"
+       sodipodi:absref="C:\data\projekte\eclipse-3.5-ws\JOSM\images\data\node.png"
+       xlink:href="C:\data\projekte\eclipse-3.5-ws\JOSM\images\data\node.png" />
+  </g>
+</svg>
Index: /trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/Main.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/Main.java	(revision 2613)
@@ -188,4 +188,5 @@
             map.mapView.removeLayer(layer);
             if (map.mapView.getAllLayers().isEmpty()) {
+                map.tearDownDialogsPane();
                 setMapFrame(null);
             }
Index: /trunk/src/org/openstreetmap/josm/actions/CloseChangesetAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/CloseChangesetAction.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/actions/CloseChangesetAction.java	(revision 2613)
@@ -2,6 +2,6 @@
 package org.openstreetmap.josm.actions;
 
+import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
 import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
 
 import java.awt.event.ActionEvent;
@@ -16,4 +16,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
 import org.openstreetmap.josm.data.osm.UserInfo;
 import org.openstreetmap.josm.gui.ExceptionDialogUtil;
@@ -49,8 +50,6 @@
     }
 
-    protected void onPostDownloadOpenChangesets(DownloadOpenChangesetsTask task) {
-        if (task.isCancelled() || task.getLastException() != null) return;
-
-        List<Changeset> openChangesets = task.getChangesets();
+    protected void onPostDownloadOpenChangesets() {
+        List<Changeset> openChangesets = ChangesetCache.getInstance().getOpenChangesets();
         if (openChangesets.isEmpty()) {
             JOptionPane.showMessageDialog(
@@ -105,5 +104,8 @@
                                 ExceptionDialogUtil.explainException(lastException);
                             }
-                            onPostDownloadOpenChangesets(DownloadOpenChangesetsTask.this);
+                            ChangesetCache.getInstance().update(changesets);
+                            if (!cancelled && lastException == null) {
+                                onPostDownloadOpenChangesets();
+                            }
                         }
                     }
@@ -146,8 +148,4 @@
         }
 
-        public List<Changeset> getChangesets() {
-            return changesets;
-        }
-
         public Exception getLastException() {
             return lastException;
Index: /trunk/src/org/openstreetmap/josm/data/osm/Changeset.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/Changeset.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/data/osm/Changeset.java	(revision 2613)
@@ -7,4 +7,5 @@
 import java.util.Map;
 
+import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.visitor.Visitor;
@@ -68,19 +69,10 @@
             setId(other.getId());
             this.incomplete = true;
+            this.tags = new HashMap<String, String>();
         } else {
-            cloneFrom(other);
+            this.id = other.id;
+            mergeFrom(other);
             this.incomplete = false;
         }
-    }
-
-    public void cloneFrom(Changeset other) {
-        setId(other.getId());
-        setUser(other.getUser());
-        setCreatedAt(other.getCreatedAt());
-        setClosedAt(other.getClosedAt());
-        setMin(other.getMin());
-        setMax(other.getMax());
-        setKeys(other.getKeys());
-        setOpen(other.isOpen());
     }
 
@@ -152,4 +144,10 @@
     public LatLon getMax() {
         return max;
+    }
+
+    public Bounds getBounds() {
+        if (min != null && max != null)
+            return new Bounds(min,max);
+        return null;
     }
 
@@ -237,12 +235,6 @@
         if (id > 0)
             return prime * result + getClass().hashCode();
-        result = prime * result + ((closedAt == null) ? 0 : closedAt.hashCode());
-        result = prime * result + ((createdAt == null) ? 0 : createdAt.hashCode());
-        result = prime * result + ((max == null) ? 0 : max.hashCode());
-        result = prime * result + ((min == null) ? 0 : min.hashCode());
-        result = prime * result + (open ? 1231 : 1237);
-        result = prime * result + ((tags == null) ? 0 : tags.hashCode());
-        result = prime * result + ((user == null) ? 0 : user.hashCode());
-        return result;
+        else
+            return super.hashCode();
     }
 
@@ -258,39 +250,5 @@
         if (this.id > 0 && other.id == this.id)
             return true;
-        if (closedAt == null) {
-            if (other.closedAt != null)
-                return false;
-        } else if (!closedAt.equals(other.closedAt))
-            return false;
-        if (createdAt == null) {
-            if (other.createdAt != null)
-                return false;
-        } else if (!createdAt.equals(other.createdAt))
-            return false;
-        if (id != other.id)
-            return false;
-        if (max == null) {
-            if (other.max != null)
-                return false;
-        } else if (!max.equals(other.max))
-            return false;
-        if (min == null) {
-            if (other.min != null)
-                return false;
-        } else if (!min.equals(other.min))
-            return false;
-        if (open != other.open)
-            return false;
-        if (tags == null) {
-            if (other.tags != null)
-                return false;
-        } else if (!tags.equals(other.tags))
-            return false;
-        if (user == null) {
-            if (other.user != null)
-                return false;
-        } else if (!user.equals(other.user))
-            return false;
-        return true;
+        return this == obj;
     }
 
@@ -318,6 +276,6 @@
         this.min = other.min;
         this.max = other.max;
-        this.tags.clear();
-        this.tags.putAll(other.tags);
+        this.tags = new HashMap<String, String>(other.tags);
+        this.incomplete = other.incomplete;
     }
 }
Index: /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCache.java	(revision 2613)
@@ -0,0 +1,137 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.osm;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Logger;
+
+public class ChangesetCache {
+    static private final Logger logger = Logger.getLogger(ChangesetCache.class.getName());
+    static private final ChangesetCache instance = new ChangesetCache();
+
+    public static ChangesetCache getInstance() {
+        return instance;
+    }
+
+    private final Map<Integer, Changeset> cache  = new HashMap<Integer, Changeset>();
+
+    private final CopyOnWriteArrayList<ChangesetCacheListener> listeners =
+        new CopyOnWriteArrayList<ChangesetCacheListener>();
+
+    private ChangesetCache() {
+    }
+
+    public void addChangesetCacheListener(ChangesetCacheListener listener) {
+        synchronized(listeners) {
+            if (listener != null && ! listeners.contains(listener)) {
+                listeners.add(listener);
+            }
+        }
+    }
+
+    public void removeChangesetCacheListener(ChangesetCacheListener listener) {
+        synchronized(listeners) {
+            if (listener != null && listeners.contains(listener)) {
+                listeners.remove(listener);
+            }
+        }
+    }
+
+    protected void fireChangesetCacheEvent(ChangesetCacheEvent e) {
+        for(ChangesetCacheListener l: listeners) {
+            l.changesetCacheUpdated(e);
+        }
+    }
+
+    protected void update(Changeset cs, DefaultChangesetCacheEvent e) {
+        if (cs == null) return;
+        if (cs.isNew()) return;
+        Changeset inCache = cache.get(cs.getId());
+        if (inCache != null) {
+            inCache.mergeFrom(cs);
+            e.rememberUpdatedChangeset(inCache);
+        } else {
+            e.rememberAddedChangeset(cs);
+            cache.put(cs.getId(), cs);
+        }
+    }
+
+    public void update(Changeset cs) {
+        DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
+        update(cs, e);
+        fireChangesetCacheEvent(e);
+    }
+
+    public void update(Collection<Changeset> changesets) {
+        if (changesets == null || changesets.isEmpty()) return;
+        DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
+        for (Changeset cs: changesets) {
+            update(cs, e);
+        }
+        fireChangesetCacheEvent(e);
+    }
+
+    public boolean contains(int id) {
+        if (id <=0) return false;
+        return cache.get(id) != null;
+    }
+
+    public boolean contains(Changeset cs) {
+        if (cs == null) return false;
+        if (cs.isNew()) return false;
+        return contains(cs.getId());
+    }
+
+    public Changeset get(int id) {
+        return cache.get(id);
+    }
+
+    protected void remove(int id, DefaultChangesetCacheEvent e) {
+        if (id <= 0) return;
+        Changeset cs = cache.get(id);
+        if (cs == null) return;
+        cache.remove(id);
+        e.rememberRemovedChangeset(cs);
+    }
+
+    public void remove(int id) {
+        DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
+        remove(id, e);
+        if (! e.isEmpty()) {
+            fireChangesetCacheEvent(e);
+        }
+    }
+
+    public void remove(Changeset cs) {
+        if (cs == null) return;
+        if (cs.isNew()) return;
+        remove(cs.getId());
+    }
+
+    public int size() {
+        return cache.size();
+    }
+
+    public void clear() {
+        DefaultChangesetCacheEvent e = new DefaultChangesetCacheEvent(this);
+        for (Changeset cs: cache.values()) {
+            e.rememberRemovedChangeset(cs);
+        }
+        cache.clear();
+        fireChangesetCacheEvent(e);
+    }
+
+    public List<Changeset> getOpenChangesets() {
+        List<Changeset> ret = new ArrayList<Changeset>();
+        for (Changeset cs: cache.values()) {
+            if (cs.isOpen()) {
+                ret.add(cs);
+            }
+        }
+        return ret;
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCacheEvent.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCacheEvent.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCacheEvent.java	(revision 2613)
@@ -0,0 +1,12 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.osm;
+
+import java.util.Collection;
+
+public interface ChangesetCacheEvent {
+    ChangesetCache getSource();
+    Collection<Changeset> getAddedChangesets();
+    Collection<Changeset> getRemovedChangesets();
+    Collection<Changeset> getUpdatedChangesets();
+
+}
Index: /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCacheListener.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCacheListener.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/data/osm/ChangesetCacheListener.java	(revision 2613)
@@ -0,0 +1,8 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.osm;
+
+
+public interface ChangesetCacheListener {
+
+    void changesetCacheUpdated(ChangesetCacheEvent event);
+}
Index: /trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 2613)
@@ -20,4 +20,5 @@
 
 import org.openstreetmap.josm.data.SelectionChangedListener;
+
 
 /**
Index: /trunk/src/org/openstreetmap/josm/data/osm/DefaultChangesetCacheEvent.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/DefaultChangesetCacheEvent.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/data/osm/DefaultChangesetCacheEvent.java	(revision 2613)
@@ -0,0 +1,54 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.osm;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class DefaultChangesetCacheEvent implements ChangesetCacheEvent{
+
+    private final Set<Changeset> added;
+    private final Set<Changeset> modified;
+    private final Set<Changeset> removed;
+    private final ChangesetCache source;
+
+    public DefaultChangesetCacheEvent(ChangesetCache source) {
+        this.source = source;
+        added = new HashSet<Changeset>();
+        modified = new HashSet<Changeset>();
+        removed = new HashSet<Changeset>();
+    }
+
+    public Collection<Changeset> getAddedChangesets() {
+        return Collections.unmodifiableCollection(added);
+    }
+    public Collection<Changeset> getRemovedChangesets() {
+        return Collections.unmodifiableCollection(removed);
+    }
+    public ChangesetCache getSource() {
+        return source;
+    }
+    public Collection<Changeset> getUpdatedChangesets() {
+        return Collections.unmodifiableCollection(modified);
+    }
+
+    public void rememberAddedChangeset(Changeset cs) {
+        if (cs == null) return;
+        added.add(cs);
+    }
+
+    public void rememberUpdatedChangeset(Changeset cs) {
+        if (cs == null) return;
+        modified.add(cs);
+    }
+
+    public void rememberRemovedChangeset(Changeset cs) {
+        if (cs == null) return;
+        removed.add(cs);
+    }
+
+    public boolean isEmpty() {
+        return added.isEmpty() && modified.isEmpty() && removed.isEmpty();
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/MapFrame.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/MapFrame.java	(revision 2613)
@@ -4,9 +4,8 @@
 
 import java.awt.BorderLayout;
-import java.awt.Component;
 import java.awt.Container;
 import java.awt.Dimension;
+import java.awt.event.MouseWheelEvent;
 import java.awt.event.MouseWheelListener;
-import java.awt.event.MouseWheelEvent;
 import java.util.ArrayList;
 import java.util.List;
@@ -16,10 +15,10 @@
 import javax.swing.BoxLayout;
 import javax.swing.ButtonGroup;
+import javax.swing.JPanel;
 import javax.swing.JSplitPane;
-import javax.swing.JPanel;
 import javax.swing.JToolBar;
 import javax.swing.border.Border;
+import javax.swing.plaf.basic.BasicSplitPaneDivider;
 import javax.swing.plaf.basic.BasicSplitPaneUI;
-import javax.swing.plaf.basic.BasicSplitPaneDivider;
 
 import org.openstreetmap.josm.Main;
@@ -30,4 +29,5 @@
 import org.openstreetmap.josm.actions.mapmode.SelectAction;
 import org.openstreetmap.josm.actions.mapmode.ZoomAction;
+import org.openstreetmap.josm.gui.dialogs.ChangesetDialog;
 import org.openstreetmap.josm.gui.dialogs.CommandStackDialog;
 import org.openstreetmap.josm.gui.dialogs.ConflictDialog;
@@ -126,6 +126,8 @@
         splitPane.setBorder(null);
         splitPane.setUI(new BasicSplitPaneUI() {
+            @Override
             public BasicSplitPaneDivider createDefaultDivider() {
                 return new BasicSplitPaneDivider(this) {
+                    @Override
                     public void setBorder(Border b) {
                     }
@@ -148,10 +150,12 @@
         addToggleDialog(new HistoryDialog());
         addToggleDialog(new SelectionListDialog());
-        if(Main.pref.getBoolean("displayfilter", false))
+        if(Main.pref.getBoolean("displayfilter", false)) {
             addToggleDialog(new FilterDialog());
+        }
         addToggleDialog(new UserListDialog());
         addToggleDialog(conflictDialog = new ConflictDialog());
         addToggleDialog(new CommandStackDialog(this));
         addToggleDialog(relationListDialog = new RelationListDialog());
+        addToggleDialog(new ChangesetDialog(this));
 
         // status line below the map
@@ -209,4 +213,11 @@
     public void initializeDialogsPane() {
         dialogsPanel.initialize(allDialogs);
+    }
+
+    /**
+     * 
+     */
+    public void tearDownDialogsPane() {
+        dialogsPanel.tearDown();
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 2613)
@@ -2,9 +2,7 @@
 package org.openstreetmap.josm.gui;
 
-import static org.openstreetmap.josm.tools.I18n.tr;
-
 import java.awt.EventQueue;
-import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.util.logging.Logger;
 
 import javax.swing.SwingUtilities;
@@ -23,4 +21,5 @@
  */
 public abstract class PleaseWaitRunnable implements Runnable, CancelListener {
+    private final static Logger logger = Logger.getLogger(PleaseWaitRunnable.class.getName());
 
     private boolean cancelled = false;
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 2613)
@@ -0,0 +1,293 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.swing.AbstractAction;
+import javax.swing.DefaultListSelectionModel;
+import javax.swing.JCheckBox;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JToolBar;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.dialogs.changeset.ChangesetInSelectionListModel;
+import org.openstreetmap.josm.gui.dialogs.changeset.ChangesetListCellRenderer;
+import org.openstreetmap.josm.gui.dialogs.changeset.ChangesetListModel;
+import org.openstreetmap.josm.gui.dialogs.changeset.ChangesetsInActiveDataLayerListModel;
+import org.openstreetmap.josm.gui.dialogs.changeset.DownloadChangesetsTask;
+import org.openstreetmap.josm.gui.help.HelpUtil;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+public class ChangesetDialog extends ToggleDialog{
+    static private final Logger logger = Logger.getLogger(ChangesetDialog.class.getName());
+
+    private ChangesetInSelectionListModel inSelectionModel;
+    private ChangesetsInActiveDataLayerListModel inActiveDataLayerModel;
+    private JList lstInSelection;
+    private JList lstInActiveDataLayer;
+    private JCheckBox cbInSelectionOnly;
+    private JPanel pnlList;
+
+    protected void buildChangesetsLists() {
+        DefaultListSelectionModel selectionModel = new DefaultListSelectionModel();
+        inSelectionModel = new ChangesetInSelectionListModel(selectionModel);
+
+        lstInSelection = new JList(inSelectionModel);
+        lstInSelection.setSelectionModel(selectionModel);
+        lstInSelection.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        lstInSelection.setCellRenderer(new ChangesetListCellRenderer());
+
+        selectionModel = new DefaultListSelectionModel();
+        inActiveDataLayerModel = new ChangesetsInActiveDataLayerListModel(selectionModel);
+        lstInActiveDataLayer = new JList(inActiveDataLayerModel);
+        lstInActiveDataLayer.setSelectionModel(selectionModel);
+        lstInActiveDataLayer.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+        lstInActiveDataLayer.setCellRenderer(new ChangesetListCellRenderer());
+
+        ChangesetCache.getInstance().addChangesetCacheListener(inSelectionModel);
+        Layer.listeners.add(inSelectionModel);
+        DataSet.selListeners.add(inSelectionModel);
+
+        ChangesetCache.getInstance().addChangesetCacheListener(inActiveDataLayerModel);
+        Layer.listeners.add(inActiveDataLayerModel);
+
+        DblClickHandler dblClickHandler = new DblClickHandler();
+        lstInSelection.addMouseListener(dblClickHandler);
+        lstInActiveDataLayer.addMouseListener(dblClickHandler);
+    }
+
+    @Override
+    public void tearDown() {
+        ChangesetCache.getInstance().removeChangesetCacheListener(inActiveDataLayerModel);
+        Layer.listeners.remove(inSelectionModel);
+        DataSet.selListeners.remove(inSelectionModel);
+        Layer.listeners.remove(inActiveDataLayerModel);
+    }
+
+    protected JPanel buildFilterPanel() {
+        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
+        pnl.setBorder(null);
+        pnl.add(cbInSelectionOnly = new JCheckBox(tr("For selected objects only")));
+        cbInSelectionOnly.setToolTipText(tr("<html>Select to show changesets for the currently selected objects only.<br>"
+                + "Unselect to show all changesets for objects in the current data layer.</html>"));
+        cbInSelectionOnly.setSelected(Main.pref.getBoolean("changeset-dialog.for-selected-objects-only", false));
+        return pnl;
+    }
+
+    protected JPanel buildListPanel() {
+        buildChangesetsLists();
+        JPanel pnl = new JPanel(new BorderLayout());
+        if (cbInSelectionOnly.isSelected()) {
+            pnl.add(new JScrollPane(lstInSelection));
+        } else {
+            pnl.add(new JScrollPane(lstInActiveDataLayer));
+        }
+        return pnl;
+    }
+
+    protected JPanel buildButtonPanel() {
+        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.LEFT));
+
+        JToolBar tp = new JToolBar(JToolBar.HORIZONTAL);
+        tp.setFloatable(false);
+
+        SelectObjectsAction selectObjectsAction = new SelectObjectsAction();
+        tp.add(selectObjectsAction);
+        cbInSelectionOnly.addItemListener(selectObjectsAction);
+        lstInActiveDataLayer.getSelectionModel().addListSelectionListener(selectObjectsAction);
+        lstInSelection.getSelectionModel().addListSelectionListener(selectObjectsAction);
+
+        ReadChangesetsAction readChangesetAction = new ReadChangesetsAction();
+        tp.add(readChangesetAction);
+        cbInSelectionOnly.addItemListener(readChangesetAction);
+        lstInActiveDataLayer.getSelectionModel().addListSelectionListener(readChangesetAction);
+        lstInSelection.getSelectionModel().addListSelectionListener(readChangesetAction);
+
+        pnl.add(tp);
+        return pnl;
+    }
+
+    protected void build() {
+        JPanel pnl = new JPanel(new BorderLayout());
+        pnl.add(buildFilterPanel(), BorderLayout.NORTH);
+        pnl.add(pnlList = buildListPanel(), BorderLayout.CENTER);
+        pnl.add(buildButtonPanel(), BorderLayout.SOUTH);
+        add(pnl, BorderLayout.CENTER);
+
+        cbInSelectionOnly.addItemListener(new FilterChangeHandler());
+
+        HelpUtil.setHelpContext(pnl, HelpUtil.ht("/Dialog/ChangesetListDialog"));
+    }
+
+    protected JList getCurrentChangesetList() {
+        if (cbInSelectionOnly.isSelected())
+            return lstInSelection;
+        return lstInActiveDataLayer;
+    }
+
+    protected ChangesetListModel getCurrentChangesetListModel() {
+        if (cbInSelectionOnly.isSelected())
+            return inSelectionModel;
+        return inActiveDataLayerModel;
+    }
+
+    protected void initWithCurrentData() {
+        if (Main.main.getEditLayer() != null) {
+            inSelectionModel.initFromPrimitives(Main.main.getEditLayer().data.getSelected());
+            inActiveDataLayerModel.initFromDataSet(Main.main.getEditLayer().data);
+        }
+    }
+
+    public ChangesetDialog(MapFrame mapFrame) {
+        super(
+                tr("Changesets"),
+                "changesetdialog",
+                tr("Open the list of changesets in the current layer."),
+                null, /* no keyboard shortcut */
+                200, /* the preferred height */
+                false /* don't show if there is no preference */
+        );
+        build();
+        initWithCurrentData();
+    }
+
+    class DblClickHandler extends MouseAdapter {
+        @Override
+        public void mouseClicked(MouseEvent e) {
+            if (!SwingUtilities.isLeftMouseButton(e) || e.getClickCount() < 2)
+                return;
+            Set<Integer> sel = getCurrentChangesetListModel().getSelectedChangesetIds();
+            if (sel.isEmpty())
+                return;
+            if (Main.main.getCurrentDataSet() == null)
+                return;
+            new SelectObjectsAction().selectObjectsByChangesetIds(Main.main.getCurrentDataSet(), sel);
+        }
+
+    }
+
+    class FilterChangeHandler implements ItemListener {
+        public void itemStateChanged(ItemEvent e) {
+            Main.pref.put("changeset-dialog.for-selected-objects-only", cbInSelectionOnly.isSelected());
+            pnlList.removeAll();
+            if (cbInSelectionOnly.isSelected()) {
+                pnlList.add(new JScrollPane(lstInSelection), BorderLayout.CENTER);
+            } else {
+                pnlList.add(new JScrollPane(lstInActiveDataLayer), BorderLayout.CENTER);
+            }
+            validate();
+            repaint();
+        }
+    }
+
+    class SelectObjectsAction extends AbstractAction implements ListSelectionListener, ItemListener{
+
+        public SelectObjectsAction() {
+            putValue(NAME, tr("Select"));
+            putValue(SHORT_DESCRIPTION, tr("Select all objects assigned to the currently selected changesets"));
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "select"));
+            updateEnabledState();
+        }
+
+        public void selectObjectsByChangesetIds(DataSet ds, Set<Integer> ids) {
+            if (ds == null || ids == null)
+                return;
+            Set<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
+            for (OsmPrimitive p: ds.getNodes()) {
+                if (ids.contains(p.getChangesetId())) {
+                    sel.add(p);
+                }
+            }
+            for (OsmPrimitive p: ds.getWays()) {
+                if (ids.contains(p.getChangesetId())) {
+                    sel.add(p);
+                }
+            }
+            for (OsmPrimitive p: ds.getRelations()) {
+                if (ids.contains(p.getChangesetId())) {
+                    sel.add(p);
+                }
+            }
+            ds.setSelected(sel);
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            if (Main.main.getEditLayer() == null)
+                return;
+            ChangesetListModel model = getCurrentChangesetListModel();
+            Set<Integer> sel = model.getSelectedChangesetIds();
+            if (sel.isEmpty())
+                return;
+
+            DataSet ds = Main.main.getEditLayer().data;
+            selectObjectsByChangesetIds(ds,sel);
+        }
+
+        protected void updateEnabledState() {
+            setEnabled(getCurrentChangesetList().getSelectedIndices().length > 0);
+        }
+
+        public void itemStateChanged(ItemEvent arg0) {
+            updateEnabledState();
+
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            updateEnabledState();
+        }
+    }
+
+    class ReadChangesetsAction extends AbstractAction implements ListSelectionListener, ItemListener{
+        public ReadChangesetsAction() {
+            putValue(NAME, tr("Download"));
+            putValue(SHORT_DESCRIPTION, tr("Download information about the selected changesets from the OSM server"));
+            putValue(SMALL_ICON, ImageProvider.get("download"));
+            updateEnabledState();
+        }
+
+        public void actionPerformed(ActionEvent arg0) {
+            ChangesetListModel model = getCurrentChangesetListModel();
+            Set<Integer> sel = model.getSelectedChangesetIds();
+            if (sel.isEmpty())
+                return;
+            DownloadChangesetsTask task = new DownloadChangesetsTask(sel);
+            Main.worker.submit(task);
+        }
+
+        protected void updateEnabledState() {
+            setEnabled(getCurrentChangesetList().getSelectedIndices().length > 0);
+        }
+
+        public void itemStateChanged(ItemEvent arg0) {
+            updateEnabledState();
+
+        }
+
+        public void valueChanged(ListSelectionEvent e) {
+            updateEnabledState();
+        }
+    }
+
+}
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/DialogsPanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/DialogsPanel.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/DialogsPanel.java	(revision 2613)
@@ -33,5 +33,5 @@
 
     public boolean initialized = false; // read only from outside
-    
+
     public void initialize(List<ToggleDialog> pAllDialogs) {
         if (initialized)
@@ -43,13 +43,24 @@
             add(pAllDialogs.get(i), false);
         }
-        
+
         this.add(mSpltPane);
         reconstruct(Action.ELEMENT_SHRINKS, null);
     }
 
+    /**
+     * Invoke before the panel is discarded. This will in turn call {@see ToggleDialog#tearDown()}
+     * on every dialog.
+     * 
+     */
+    public void tearDown() {
+        for(ToggleDialog dialog: allDialogs) {
+            dialog.tearDown();
+        }
+    }
+
     public void add(ToggleDialog dlg) {
         add(dlg, true);
     }
-    
+
     public void add(ToggleDialog dlg, boolean doReconstruct) {
         allDialogs.add(dlg);
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java	(revision 2613)
@@ -68,5 +68,5 @@
      */
     protected boolean isCollapsed;
-    
+
     /** the preferred height if the toggle dialog is expanded */
     private int preferredHeight;
@@ -120,5 +120,4 @@
         isDocked = Main.pref.getBoolean(preferencePrefix+".docked", true);
         isCollapsed = Main.pref.getBoolean(preferencePrefix+".minimized", false);
-        //System.err.println(name+": showing="+isShowing+" docked="+isDocked+" collapsed="+isCollapsed);
     }
 
@@ -214,5 +213,5 @@
      */
     public void collapse() {
-//        if (isShowing && isDocked && !isCollapsed) {
+        //        if (isShowing && isDocked && !isCollapsed) {
         if (isDialogInDefaultView()) {
             setContentVisible(false);
@@ -231,5 +230,5 @@
      */
     protected void expand() {
-//        if (isShowing && isDocked && isCollapsed) {
+        //        if (isShowing && isDocked && isCollapsed) {
         if (isDialogInCollapsedView()) {
             setContentVisible(true);
@@ -529,6 +528,6 @@
 
     /**
-    * Change the Geometry of the detached dialog to better fit the content.
-    */
+     * Change the Geometry of the detached dialog to better fit the content.
+     */
     protected Rectangle getDetachedGeometry(Rectangle last) {
         return last;
@@ -552,5 +551,5 @@
         return true;
     }
-    
+
     /**
      * primitive stateChangedListener for subclasses
@@ -559,6 +558,14 @@
     }
 
-    /***
-     * End of override hooks
-     **/
+    /**
+     * This method is called by hosting panel before the panel with the toggle dialogs
+     * and the toggle dialogs themself are discared, for instance because no layer is
+     * left in JOSM and  the main screen turns from the map editor to the MOTD panel.
+     * 
+     * Override in subclasses to unregister as listener. After tearDown() is invoked
+     * the dialog should be registered as listener.
+     * 
+     * The default implementation is empty.
+     */
+    public void tearDown() {}
 }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetInSelectionListModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetInSelectionListModel.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetInSelectionListModel.java	(revision 2613)
@@ -0,0 +1,38 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.changeset;
+
+import java.util.Collection;
+
+import javax.swing.DefaultListSelectionModel;
+
+import org.openstreetmap.josm.data.SelectionChangedListener;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
+
+public class ChangesetInSelectionListModel extends ChangesetListModel implements SelectionChangedListener, LayerChangeListener{
+
+    public ChangesetInSelectionListModel(DefaultListSelectionModel selectionModel) {
+        super(selectionModel);
+    }
+    /* ---------------------------------------------------------------------------- */
+    /* Interface SelectionChangeListener                                            */
+    /* ---------------------------------------------------------------------------- */
+    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
+        initFromPrimitives(newSelection);
+    }
+
+    /* ---------------------------------------------------------------------------- */
+    /* Interface LayerChangeListener                                                */
+    /* ---------------------------------------------------------------------------- */
+    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+        if (newLayer == null || ! (newLayer instanceof OsmDataLayer)) {
+            setChangesets(null);
+        } else if (newLayer instanceof OsmDataLayer){
+            initFromPrimitives(((OsmDataLayer) newLayer).data.getSelected());
+        }
+    }
+    public void layerAdded(Layer newLayer) {}
+    public void layerRemoved(Layer oldLayer) {}
+}
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetListCellRenderer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetListCellRenderer.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetListCellRenderer.java	(revision 2613)
@@ -0,0 +1,56 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.changeset;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Component;
+
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.ListCellRenderer;
+import javax.swing.UIManager;
+
+import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+public class ChangesetListCellRenderer extends JLabel implements ListCellRenderer{
+
+    public ChangesetListCellRenderer() {
+        setOpaque(true);
+        setIcon(ImageProvider.get("data", "changeset"));
+    }
+
+    protected void renderColors(boolean selected) {
+        if (selected) {
+            setForeground(UIManager.getColor("List.selectionForeground"));
+            setBackground(UIManager.getColor("List.selectionBackground"));
+        } else {
+            setForeground(UIManager.getColor("List.foreground"));
+            setBackground(UIManager.getColor("List.background"));
+        }
+    }
+
+    protected void renderLabel(Changeset cs) {
+        StringBuffer sb = new StringBuffer();
+        if (cs.isIncomplete()) {
+            sb.append(tr("{0} [incomplete]", cs.getId()));
+        } else {
+            String comment = cs.get("comment");
+            sb.append(cs.getId());
+            sb.append(" - ");
+            sb.append(cs.isOpen() ? tr("open") : tr("closed"));
+            if (comment != null) {
+                sb.append(" - ").append("'").append(comment).append("'");
+            }
+        }
+        setText(sb.toString());
+    }
+
+    public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
+            boolean cellHasFocus) {
+        Changeset cs = (Changeset)value;
+        renderColors(isSelected);
+        renderLabel(cs);
+        return this;
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetListModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetListModel.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetListModel.java	(revision 2613)
@@ -0,0 +1,191 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.changeset;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.swing.DefaultListModel;
+import javax.swing.DefaultListSelectionModel;
+
+import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
+import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
+import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+
+public class ChangesetListModel extends DefaultListModel  implements ChangesetCacheListener{
+    static private final Logger logger = Logger.getLogger(ChangesetListModel.class.getName());
+
+    private final List<Changeset> data = new ArrayList<Changeset>();
+    private DefaultListSelectionModel selectionModel;
+
+    public ChangesetListModel(DefaultListSelectionModel selectionModel) {
+        this.selectionModel = selectionModel;
+    }
+
+    public Set<Changeset> getSelectedChangesets() {
+        Set<Changeset> ret = new HashSet<Changeset>();
+        for (int i=0; i < getSize(); i++) {
+            if (selectionModel.isSelectedIndex(i)) {
+                ret.add(data.get(i));
+            }
+        }
+        return ret;
+    }
+
+    public Set<Integer> getSelectedChangesetIds() {
+        Set<Integer> ret = new HashSet<Integer>();
+        for (int i=0; i < getSize(); i++) {
+            if (selectionModel.isSelectedIndex(i)) {
+                ret.add(data.get(i).getId());
+            }
+        }
+        return ret;
+    }
+
+    public void setSelectedChangesets(Collection<Changeset> changesets) {
+        selectionModel.clearSelection();
+        if (changesets == null) return;
+        for (Changeset cs: changesets) {
+            int idx = data.indexOf(cs);
+            if (idx < 0) {
+                continue;
+            }
+            selectionModel.addSelectionInterval(idx,idx);
+        }
+    }
+
+    protected void setChangesets(Collection<Changeset> changesets) {
+        Set<Changeset> sel = getSelectedChangesets();
+        data.clear();
+        if (changesets == null) {
+            fireContentsChanged(this, 0, getSize());
+            return;
+        }
+        data.addAll(changesets);
+        ChangesetCache cache = ChangesetCache.getInstance();
+        for (Changeset cs: data) {
+            if (cache.contains(cs) && cache.get(cs.getId()) != cs) {
+                cs.mergeFrom(cache.get(cs.getId()));
+            }
+        }
+        sort();
+        fireIntervalAdded(this, 0, getSize());
+        setSelectedChangesets(sel);
+    }
+
+    public void initFromChangesetIds(Collection<Integer> ids) {
+        if (ids == null || ids.isEmpty()) {
+            setChangesets(null);
+            return;
+        }
+        Set<Changeset> changesets = new HashSet<Changeset>(ids.size());
+        for (int id: ids) {
+            if (id <= 0) {
+                continue;
+            }
+            changesets.add(new Changeset(id));
+        }
+        setChangesets(changesets);
+    }
+
+    public void initFromPrimitives(Collection<? extends OsmPrimitive> primitives) {
+        if (primitives == null) {
+            setChangesets(null);
+            return;
+        }
+        Set<Changeset> changesets = new HashSet<Changeset>();
+        for (OsmPrimitive p: primitives) {
+            if (p.getChangesetId() <= 0) {
+                continue;
+            }
+            changesets.add(new Changeset(p.getChangesetId()));
+        }
+        setChangesets(changesets);
+    }
+
+    public void initFromDataSet(DataSet ds) {
+        if (ds == null) {
+            setChangesets(null);
+            return;
+        }
+        Set<Changeset> changesets = new HashSet<Changeset>();
+        for (OsmPrimitive p: ds.getNodes()) {
+            if (p.getChangesetId() <=0 ) {
+                continue;
+            }
+            changesets.add(new Changeset(p.getChangesetId()));
+        }
+        for (OsmPrimitive p: ds.getWays()) {
+            if (p.getChangesetId() <=0 ) {
+                continue;
+            }
+            changesets.add(new Changeset(p.getChangesetId()));
+        }
+        for (OsmPrimitive p: ds.getRelations()) {
+            if (p.getChangesetId() <=0 ) {
+                continue;
+            }
+            changesets.add(new Changeset(p.getChangesetId()));
+        }
+        setChangesets(changesets);
+    }
+
+    @Override
+    public Object getElementAt(int idx) {
+        return data.get(idx);
+    }
+
+    @Override
+    public int getSize() {
+        return data.size();
+    }
+
+    protected void sort() {
+        Collections.sort(
+                data,
+                new Comparator<Changeset>() {
+                    public int compare(Changeset cs1, Changeset cs2) {
+                        if (cs1.getId() > cs2.getId()) return -1;
+                        if (cs1.getId() == cs2.getId()) return 0;
+                        return 1;
+                    }
+                }
+        );
+    }
+
+    /* ---------------------------------------------------------------------------- */
+    /* Interface ChangesetCacheListener                                             */
+    /* ---------------------------------------------------------------------------- */
+    public void changesetCacheUpdated(ChangesetCacheEvent event) {
+        Set<Changeset> sel = getSelectedChangesets();
+        for(Changeset cs: event.getAddedChangesets()) {
+            int idx = data.indexOf(cs);
+            if (idx >= 0 && data.get(idx) != cs) {
+                data.get(idx).mergeFrom(cs);
+            }
+        }
+        for(Changeset cs: event.getUpdatedChangesets()) {
+            int idx = data.indexOf(cs);
+            if (idx >= 0 && data.get(idx) != cs) {
+                data.get(idx).mergeFrom(cs);
+            }
+        }
+        for(Changeset cs: event.getRemovedChangesets()) {
+            int idx = data.indexOf(cs);
+            if (idx >= 0) {
+                // replace with an incomplete changeset
+                data.set(idx, new Changeset(cs.getId()));
+            }
+        }
+        fireContentsChanged(this, 0, getSize());
+        setSelectedChangesets(sel);
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetsInActiveDataLayerListModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetsInActiveDataLayerListModel.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetsInActiveDataLayerListModel.java	(revision 2613)
@@ -0,0 +1,47 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.changeset;
+
+import javax.swing.DefaultListSelectionModel;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.layer.DataChangeListener;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.Layer.LayerChangeListener;
+
+public class ChangesetsInActiveDataLayerListModel extends ChangesetListModel implements LayerChangeListener, DataChangeListener{
+
+    public ChangesetsInActiveDataLayerListModel(DefaultListSelectionModel selectionModel) {
+        super(selectionModel);
+    }
+
+    /* ---------------------------------------------------------------------------- */
+    /* Interface LayerChangeListener                                                */
+    /* ---------------------------------------------------------------------------- */
+    public void activeLayerChange(Layer oldLayer, Layer newLayer) {
+        if (oldLayer != null && oldLayer instanceof OsmDataLayer) {
+            OsmDataLayer l = (OsmDataLayer)oldLayer;
+            l.listenerDataChanged.remove(this);
+        }
+        if (newLayer == null) {
+            setChangesets(null);
+        } else if (newLayer instanceof OsmDataLayer){
+            OsmDataLayer l = (OsmDataLayer)newLayer;
+            l.listenerDataChanged.add(this);
+            initFromDataSet(l.data);
+        } else {
+            setChangesets(null);
+        }
+    }
+    public void layerAdded(Layer newLayer) {}
+    public void layerRemoved(Layer oldLayer) {}
+
+    /* ---------------------------------------------------------------------------- */
+    /* Interface DataChangeListener                                                 */
+    /* ---------------------------------------------------------------------------- */
+    public void dataChanged(OsmDataLayer l) {
+        if (l == null) return;
+        if (l != Main.main.getEditLayer()) return;
+        initFromDataSet(l.data);
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/DownloadChangesetsTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/DownloadChangesetsTask.java	(revision 2613)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/DownloadChangesetsTask.java	(revision 2613)
@@ -0,0 +1,89 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.dialogs.changeset;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
+import org.openstreetmap.josm.gui.ExceptionDialogUtil;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.io.OsmServerChangesetReader;
+import org.openstreetmap.josm.io.OsmTransferException;
+import org.xml.sax.SAXException;
+
+public class DownloadChangesetsTask extends PleaseWaitRunnable{
+
+    private Set<Integer> idsToDownload;
+    private OsmServerChangesetReader reader;
+    private boolean cancelled;
+    private Exception lastException;
+    private List<Changeset> downloadedChangesets;
+
+    public DownloadChangesetsTask(Collection<Integer> ids) {
+        super(tr("Download changesets"));
+        idsToDownload = new HashSet<Integer>();
+        if (ids == null ||  ids.isEmpty())
+            return;
+        for (int id: ids) {
+            if (id <= 0) {
+                continue;
+            }
+            idsToDownload.add(id);
+        }
+    }
+
+    @Override
+    protected void cancel() {
+        cancelled = true;
+        synchronized (this) {
+            if (reader != null) {
+                reader.cancel();
+            }
+        }
+    }
+
+    @Override
+    protected void finish() {
+        if (cancelled)
+            return;
+        if (lastException != null) {
+            ExceptionDialogUtil.explainException(lastException);
+        }
+        Runnable r = new Runnable() {
+            public void run() {
+                ChangesetCache.getInstance().update(downloadedChangesets);
+            }
+        };
+
+        if (SwingUtilities.isEventDispatchThread()) {
+            r.run();
+        } else {
+            SwingUtilities.invokeLater(r);
+        }
+    }
+
+    @Override
+    protected void realRun() throws SAXException, IOException, OsmTransferException {
+        try {
+            synchronized (this) {
+                reader = new OsmServerChangesetReader();
+            }
+            downloadedChangesets = reader.readChangesets(idsToDownload, getProgressMonitor().createSubTaskMonitor(0, false));
+        } catch(Exception e) {
+            if (cancelled)
+                // ignore exception if cancelled
+                return;
+            if (e instanceof RuntimeException)
+                throw (RuntimeException)e;
+            lastException = e;
+        }
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/io/ChangesetManagementPanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/ChangesetManagementPanel.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/io/ChangesetManagementPanel.java	(revision 2613)
@@ -26,4 +26,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
 import org.openstreetmap.josm.gui.JMultilineLabel;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -104,4 +105,5 @@
         gc.weightx = 1.0;
         model = new OpenChangesetComboBoxModel();
+        ChangesetCache.getInstance().addChangesetCacheListener(model);
         cbOpenChangesets = new JComboBox(model);
         cbOpenChangesets.setToolTipText("Select an open changeset");
@@ -171,4 +173,12 @@
     }
 
+    public void setSelectedChangesetForNextUpload(Changeset cs) {
+        int idx  = model.getIndexOf(cs);
+        if (idx >=0) {
+            rbExisting.setSelected(true);
+            model.setSelectedItem(cs);
+        }
+    }
+
     /**
      * Replies the currently selected changeset. null, if no changeset is
@@ -203,32 +213,4 @@
     }
 
-    public void updateListOfChangesetsAfterUploadOperation(Changeset cs) {
-        if (cs == null || cs.isNew()) {
-            model.setSelectedItem(null);
-        } else if (cs.isOpen()){
-            if (cs.get("created_by") == null) {
-                cs.put("created_by", getDefaultCreatedBy());
-            }
-            model.addOrUpdate(cs);
-            cs = model.getChangesetById(cs.getId());
-            model.setSelectedItem(cs);
-            rbExisting.setSelected(true);
-        } else if (!cs.isOpen()){
-            removeChangeset(cs);
-            rbUseNew.setSelected(true);
-        }
-    }
-
-    /**
-     * Remove a changeset from the list of open changeset
-     *
-     * @param cs the changeset to be removed. Ignored if null.
-     */
-    public void removeChangeset(Changeset cs) {
-        if (cs ==  null) return;
-        model.removeChangeset(cs);
-        refreshGUI();
-    }
-
     /* ---------------------------------------------------------------------------- */
     /* Interface ListDataListener                                                   */
@@ -256,4 +238,7 @@
             if (rbExisting.isSelected()) {
                 firePropertyChange(SELECTED_CHANGESET_PROP, null, cs);
+                if (cs == null) {
+                    rbUseNew.setSelected(true);
+                }
             }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/io/CloseChangesetDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/CloseChangesetDialog.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/io/CloseChangesetDialog.java	(revision 2613)
@@ -1,4 +1,6 @@
 // License: GPL. For details, see LICENSE file.
 package org.openstreetmap.josm.gui.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.awt.BorderLayout;
@@ -6,4 +8,7 @@
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -12,4 +17,5 @@
 import javax.swing.BorderFactory;
 import javax.swing.DefaultListModel;
+import javax.swing.JComponent;
 import javax.swing.JDialog;
 import javax.swing.JLabel;
@@ -18,4 +24,5 @@
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
+import javax.swing.KeyStroke;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -26,6 +33,4 @@
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.WindowGeometry;
-
-import static org.openstreetmap.josm.tools.I18n.tr;
 
 /**
@@ -41,4 +46,6 @@
     /** the list model */
     private DefaultListModel model;
+
+    private SideButton btnCloseChangesets;
 
     protected JPanel buildTopPanel() {
@@ -66,6 +73,13 @@
         CloseAction closeAction = new CloseAction();
         lstOpenChangesets.addListSelectionListener(closeAction);
-        pnl.add(new SideButton(closeAction));
-        pnl.add(new SideButton(new CancelAction()));
+        pnl.add(btnCloseChangesets = new SideButton(closeAction));
+        btnCloseChangesets.setFocusable(true);
+        btnCloseChangesets.getInputMap(JComponent.WHEN_FOCUSED).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0), "enter");
+        btnCloseChangesets.getActionMap().put("enter",closeAction);
+
+        // -- cancel action
+        SideButton btn;
+        pnl.add(btn = new SideButton(new CancelAction()));
+        btn.setFocusable(true);
         return pnl;
     }
@@ -77,4 +91,8 @@
         getContentPane().add(buildCenterPanel(), BorderLayout.CENTER);
         getContentPane().add(buildSouthPanel(), BorderLayout.SOUTH);
+
+        getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0), "escape");
+        getRootPane().getActionMap().put("escape", new CancelAction());
+        addWindowListener(new WindowEventHandler());
     }
 
@@ -127,8 +145,26 @@
         }
 
-        public void actionPerformed(ActionEvent e) {
+        public void cancel() {
             setCanceled(true);
             setVisible(false);
         }
+
+        public void actionPerformed(ActionEvent e) {
+            cancel();
+        }
+    }
+
+    class WindowEventHandler extends WindowAdapter {
+
+        @Override
+        public void windowActivated(WindowEvent arg0) {
+            btnCloseChangesets.requestFocusInWindow();
+        }
+
+        @Override
+        public void windowClosing(WindowEvent arg0) {
+            new CancelAction().cancel();
+        }
+
     }
 
@@ -162,4 +198,7 @@
         for (Changeset cs: changesets) {
             model.addElement(cs);
+        }
+        if (!changesets.isEmpty()) {
+            lstOpenChangesets.getSelectionModel().setSelectionInterval(0, changesets.size()-1);
         }
     }
Index: /trunk/src/org/openstreetmap/josm/gui/io/CloseChangesetTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/CloseChangesetTask.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/io/CloseChangesetTask.java	(revision 2613)
@@ -11,4 +11,5 @@
 
 import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
 import org.openstreetmap.josm.gui.ExceptionDialogUtil;
 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
@@ -59,7 +60,5 @@
                 new Runnable() {
                     public void run() {
-                        for (Changeset cs: closedChangesets) {
-                            UploadDialog.getUploadDialog().updateListOfChangesetsAfterUploadOperation(cs);
-                        }
+                        ChangesetCache.getInstance().update(closedChangesets);
                     }
                 }
Index: /trunk/src/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTask.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/io/DownloadOpenChangesetsTask.java	(revision 2613)
@@ -12,4 +12,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
 import org.openstreetmap.josm.data.osm.UserInfo;
 import org.openstreetmap.josm.gui.ExceptionDialogUtil;
@@ -70,5 +71,5 @@
                 new Runnable() {
                     public void run() {
-                        model.setChangesets(changesets);
+                        ChangesetCache.getInstance().update(changesets);
                     }
                 }
Index: /trunk/src/org/openstreetmap/josm/gui/io/OpenChangesetComboBoxModel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/OpenChangesetComboBoxModel.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/io/OpenChangesetComboBoxModel.java	(revision 2613)
@@ -2,8 +2,5 @@
 package org.openstreetmap.josm.gui.io;
 
-import static org.openstreetmap.josm.tools.I18n.tr;
-
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
@@ -11,4 +8,7 @@
 
 import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
+import org.openstreetmap.josm.data.osm.ChangesetCacheEvent;
+import org.openstreetmap.josm.data.osm.ChangesetCacheListener;
 
 /**
@@ -16,5 +16,5 @@
  *
  */
-public class OpenChangesetComboBoxModel extends DefaultComboBoxModel {
+public class OpenChangesetComboBoxModel extends DefaultComboBoxModel implements ChangesetCacheListener {
     private List<Changeset> changesets;
     private long uid;
@@ -32,48 +32,13 @@
     }
 
-    protected void internalAddOrUpdate(Changeset cs) {
-        Changeset other = getChangesetById(cs.getId());
-        if (other != null) {
-            cs.cloneFrom(other);
+    public void refresh() {
+        changesets.clear();
+        changesets.addAll(ChangesetCache.getInstance().getOpenChangesets());
+        fireContentsChanged(this, 0, getSize());
+        int idx = changesets.indexOf(selectedChangeset);
+        if (idx < 0) {
+            setSelectedItem(null);
         } else {
-            changesets.add(cs);
-        }
-    }
-
-    public void addOrUpdate(Changeset cs) {
-        if (cs.getId() <= 0 )
-            throw new IllegalArgumentException(tr("Changeset ID > 0 expected. Got {0}.", cs.getId()));
-        internalAddOrUpdate(cs);
-        fireContentsChanged(this, 0, getSize());
-    }
-
-    public void remove(long id) {
-        Changeset cs = getChangesetById(id);
-        if (cs != null) {
-            changesets.remove(cs);
-        }
-        fireContentsChanged(this, 0, getSize());
-    }
-
-    public void setChangesets(Collection<Changeset> changesets) {
-        this.changesets.clear();
-        if (changesets != null) {
-            for (Changeset cs: changesets) {
-                internalAddOrUpdate(cs);
-            }
-        }
-        fireContentsChanged(this, 0, getSize());
-        if (getSelectedItem() == null && !this.changesets.isEmpty()) {
-            setSelectedItem(this.changesets.get(0));
-        } else if (getSelectedItem() != null) {
-            if (changesets.contains(getSelectedItem())) {
-                setSelectedItem(getSelectedItem());
-            } else if (!this.changesets.isEmpty()){
-                setSelectedItem(this.changesets.get(0));
-            } else {
-                setSelectedItem(null);
-            }
-        } else {
-            setSelectedItem(null);
+            setSelectedItem(changesets.get(idx));
         }
     }
@@ -95,12 +60,11 @@
     }
 
-    public void removeChangeset(Changeset cs) {
-        if (cs == null) return;
-        changesets.remove(cs);
-        if (selectedChangeset == cs) {
-            selectFirstChangeset();
-        }
-        fireContentsChanged(this, 0, getSize());
+    /* ------------------------------------------------------------------------------------ */
+    /* ChangesetCacheListener                                                               */
+    /* ------------------------------------------------------------------------------------ */
+    public void changesetCacheUpdated(ChangesetCacheEvent event) {
+        refresh();
     }
+
     /* ------------------------------------------------------------------------------------ */
     /* ComboBoxModel                                                                        */
Index: /trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/io/UploadDialog.java	(revision 2613)
@@ -289,4 +289,8 @@
     }
 
+    public void setSelectedChangesetForNextUpload(Changeset cs) {
+        pnlChangesetManagement.setSelectedChangesetForNextUpload(cs);
+    }
+
     /**
      * Replies the {@see UploadStrategySpecification} the user entered in the dialog.
@@ -298,29 +302,4 @@
         spec.setCloseChangesetAfterUpload(pnlChangesetManagement.isCloseChangesetAfterUpload());
         return spec;
-    }
-
-    /**
-     * Sets or updates the changeset cs.
-     * If cs is null, does nothing.
-     * If cs.getId() == 0 does nothing.
-     * If cs.getId() > 0 and cs is open, adds it to the list of open
-     * changesets. If it is closed, removes it from the list of open
-     * changesets.
-     *
-     * @param cs the changeset
-     */
-    public void updateListOfChangesetsAfterUploadOperation(Changeset cs) {
-        pnlChangesetManagement.updateListOfChangesetsAfterUploadOperation(cs);
-    }
-
-    /**
-     * Removes <code>cs</code> from the list of open changesets in the upload
-     * dialog
-     *
-     * @param cs the changeset. Ignored if null.
-     */
-    public void removeChangeset(Changeset cs) {
-        if (cs == null) return;
-        pnlChangesetManagement.removeChangeset(cs);
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 2613)
@@ -18,4 +18,5 @@
 import org.openstreetmap.josm.data.APIDataSet;
 import org.openstreetmap.josm.data.osm.Changeset;
+import org.openstreetmap.josm.data.osm.ChangesetCache;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.DefaultNameFormatter;
@@ -139,5 +140,5 @@
         // make sure the current changeset is removed from the upload dialog.
         //
-        UploadDialog.getUploadDialog().removeChangeset(changeset);
+        ChangesetCache.getInstance().update(changeset);
         Changeset newChangeSet = new Changeset();
         newChangeSet.setKeys(this.changeset.getKeys());
@@ -211,12 +212,5 @@
                 layer.fireDataChange();
                 layer.onPostUploadToServer();
-
-                // make sure the upload dialog lists all known open changesets
-                //
-                if (lastException != null && lastException instanceof ChangesetClosedException) {
-                    UploadDialog.getUploadDialog().removeChangeset(changeset);
-                } else {
-                    UploadDialog.getUploadDialog().updateListOfChangesetsAfterUploadOperation(changeset);
-                }
+                ChangesetCache.getInstance().update(changeset);
             }
         };
@@ -298,6 +292,4 @@
         if (uploadCancelled)
             return;
-        if (lastException == null)
-            return;
 
         // depending on the success of the upload operation and on the policy for
@@ -309,4 +301,13 @@
         Runnable r = new Runnable() {
             public void run() {
+                // if the changeset is still open after this upload we want it to
+                // be selected on the next upload
+                //
+                ChangesetCache.getInstance().update(changeset);
+                if (changeset != null && changeset.isOpen()) {
+                    UploadDialog.getUploadDialog().setSelectedChangesetForNextUpload(changeset);
+                }
+                if (lastException == null)
+                    return;
                 if (lastException instanceof ChangesetClosedException) {
                     ChangesetClosedException e = (ChangesetClosedException)lastException;
@@ -337,5 +338,9 @@
             }
         };
-        SwingUtilities.invokeLater(r);
+        if (SwingUtilities.isEventDispatchThread()) {
+            r.run();
+        } else {
+            SwingUtilities.invokeLater(r);
+        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/io/OsmServerChangesetReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmServerChangesetReader.java	(revision 2612)
+++ /trunk/src/org/openstreetmap/josm/io/OsmServerChangesetReader.java	(revision 2613)
@@ -2,5 +2,12 @@
 package org.openstreetmap.josm.io;
 
+import static org.openstreetmap.josm.tools.I18n.tr;
+import static org.openstreetmap.josm.tools.I18n.trn;
+
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 
@@ -9,5 +16,4 @@
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import static org.openstreetmap.josm.tools.I18n.tr;
 
 /**
@@ -68,5 +74,5 @@
 
     /**
-     * Reads teh changeset with id <code>id</code> from the server
+     * Reads the changeset with id <code>id</code> from the server
      *
      * @param id  the changeset id. id > 0 required.
@@ -104,4 +110,53 @@
 
     /**
+     * Reads the changeset with id <code>id</code> from the server
+     *
+     * @param ids  the list of ids. Ignored if null. Only load changesets for ids > 0.
+     * @param monitor the progress monitor. Set to {@see NullProgressMonitor#INSTANCE} if null
+     * @return the changeset read
+     * @throws OsmTransferException thrown if something goes wrong
+     * @throws IllegalArgumentException if id <= 0
+     */
+    public List<Changeset> readChangesets(Collection<Integer> ids, ProgressMonitor monitor) throws OsmTransferException {
+        if (ids == null)
+            return Collections.emptyList();
+        if (monitor == null) {
+            monitor = NullProgressMonitor.INSTANCE;
+        }
+        try {
+            monitor.beginTask(trn("Downloading {0} changeset ...", "Downloading {0} changesets ...",ids.size(),ids.size()));
+            monitor.setTicksCount(ids.size());
+            List<Changeset> ret = new ArrayList<Changeset>();
+            int i=0;
+            for (Iterator<Integer> it = ids.iterator(); it.hasNext(); ) {
+                int id = it.next();
+                if (id <= 0) {
+                    continue;
+                }
+                i++;
+                StringBuffer sb = new StringBuffer();
+                sb.append("changeset/").append(id);
+                InputStream in = getInputStream(sb.toString(), monitor.createSubTaskMonitor(1, true));
+                if (in == null)
+                    return null;
+                monitor.indeterminateSubTask(tr("({0}/{1}) Downloading changeset {0} ...", i,ids.size(), id));
+                List<Changeset> changesets = OsmChangesetParser.parse(in, monitor.createSubTaskMonitor(1, true));
+                if (changesets == null || changesets.isEmpty()) {
+                    continue;
+                }
+                ret.addAll(changesets);
+                monitor.worked(1);
+            }
+            return ret;
+        } catch(OsmTransferException e) {
+            throw e;
+        } catch(IllegalDataException e) {
+            throw new OsmTransferException(e);
+        } finally {
+            monitor.finishTask();
+        }
+    }
+
+    /**
      * not implemented yet
      *
Index: /trunk/test/unit/org/openstreetmap/josm/data/osm/ChangesetCacheTest.groovy
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/data/osm/ChangesetCacheTest.groovy	(revision 2613)
+++ /trunk/test/unit/org/openstreetmap/josm/data/osm/ChangesetCacheTest.groovy	(revision 2613)
@@ -0,0 +1,167 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.osm;
+
+import java.net.InetAddress.Cache;
+import org.junit.Test 
+
+
+import static org.junit.Assert.*;
+
+class ChangesetCacheTest {
+	
+	@Test
+	public void test_Constructor() {
+	    ChangesetCache cache = ChangesetCache.getInstance()
+		assert cache != null
+	}
+	
+	@Test
+	public void test_addAndRemoveListeners() {
+		ChangesetCache cache = ChangesetCache.getInstance()
+		cache.clear()
+		
+		// should work
+		cache.addChangesetCacheListener null
+		
+		// should work 
+		def listener = new ChangesetCacheListener() {
+			public void changesetCacheUpdated(ChangesetCacheEvent event) {} 
+		}		
+		cache.addChangesetCacheListener listener
+		// adding a second time - should work too
+		cache.addChangesetCacheListener listener
+		assert cache.@listeners.size() == 1 // ... but only added once 
+		
+		cache.removeChangesetCacheListener null
+		
+		cache.removeChangesetCacheListener listener 
+		assert cache.@listeners.size() == 0
+	}
+	
+	@Test
+	public void update_get_remove_cycle() {
+		ChangesetCache cache = ChangesetCache.getInstance()
+		cache.clear()
+		
+		cache.update new Changeset(1)
+		assert cache.size() == 1
+		assert cache.get(1) != null
+		assert cache.get(1).id == 1
+		cache.remove(1)
+		assert cache.size() == 0
+	}
+	
+	@Test
+	public void updateTwice() {
+		ChangesetCache cache = ChangesetCache.getInstance()
+		cache.clear()
+
+		Changeset cs = new Changeset(1)
+		cs.incomplete = false
+		cs.put "key1", "value1"
+		cs.open = true
+		cache.update cs
+		
+		Changeset cs2 = new Changeset(cs)
+		assert cs2 != null
+		cs2.put "key2", "value2"
+		cs2.open = false
+		cache.update(cs2)
+		
+		assert cache.size() == 1
+		assert cache.get(1) != null
+		
+		cs = cache.get(1)
+		assert cs.get("key1") == "value1"
+		assert cs.get("key2") == "value2"
+		assert !cs.open		
+	}
+	
+	
+	@Test
+	public void contains() {
+		ChangesetCache cache = ChangesetCache.getInstance()
+		cache.@listeners.clear()
+		cache.clear()
+		
+		
+		Changeset cs = new Changeset(1)
+		cache.update cs
+		
+		assert cache.contains(1)
+		assert cache.contains(cs)
+		assert cache.contains(new Changeset(cs))
+		
+		assert ! cache.contains(2)
+		assert ! cache.contains(new Changeset(2))
+		assert ! cache.contains(null)
+	}
+	
+	@Test
+	public void fireingEvents_AddAChangeset() {
+		ChangesetCache cache = ChangesetCache.getInstance()
+		cache.clear()
+		cache.@listeners.clear()
+		
+		// should work 
+		def listener = new ChangesetCacheListener() {
+					public void changesetCacheUpdated(ChangesetCacheEvent event) {
+					    assert event != null
+						assert event.getAddedChangesets().size() == 1
+						assert event.getRemovedChangesets().empty
+						assert event.getUpdatedChangesets().empty
+						assert event.getSource() == cache 
+					} 
+		}   
+		cache.addChangesetCacheListener listener
+		cache.update(new Changeset(1))
+		cache.removeChangesetCacheListener listener
+	}
+	
+	@Test
+	public void fireingEvents_UpdateChangeset() {
+		ChangesetCache cache = ChangesetCache.getInstance()
+		cache.clear()
+		cache.@listeners.clear()
+		
+		// should work 
+		def listener = new ChangesetCacheListener() {
+					public void changesetCacheUpdated(ChangesetCacheEvent event) {
+						assert event != null
+						assert event.getAddedChangesets().empty
+						assert event.getRemovedChangesets().empty
+						assert event.getUpdatedChangesets().size() == 1
+						assert event.getSource() == cache 
+					} 
+				}   
+		cache.update(new Changeset(1))
+		
+		cache.addChangesetCacheListener listener
+		cache.update(new Changeset(1))
+		cache.removeChangesetCacheListener listener
+	}
+	
+	@Test
+	public void fireingEvents_RemoveChangeset() {
+		ChangesetCache cache = ChangesetCache.getInstance()
+		cache.clear()
+		cache.@listeners.clear()
+		
+		// should work 
+		def listener = new ChangesetCacheListener() {
+					public void changesetCacheUpdated(ChangesetCacheEvent event) {
+						assert event != null
+						assert event.getAddedChangesets().empty
+						assert event.getRemovedChangesets().size() == 1
+						assert event.getUpdatedChangesets().empty
+						assert event.getSource() == cache 
+					} 
+				}   
+		cache.update(new Changeset(1))
+		
+		cache.addChangesetCacheListener listener
+		cache.remove 1
+		cache.removeChangesetCacheListener listener
+	}
+	
+}
